Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
42866b9
fix(parser): turn the filter length and nesting limits off by default
pdevito3 Sep 30, 2026
a947ebb
fix(config): match a property max depth by path prefix again
pdevito3 Sep 30, 2026
2b1c252
fix(filter): accept only one word on the right side again
pdevito3 Sep 30, 2026
7653edb
fix(filter): build TimeOnly literals with the five-int constructor again
pdevito3 Sep 30, 2026
a3a4d54
fix(filter): throw ArgumentException for an unknown property in arith…
pdevito3 Sep 30, 2026
2f33f60
fix(filter): reopen the prevent-setting paths that v1.14.2 did not check
pdevito3 Sep 30, 2026
c0e9914
fix(filter): throw InvalidOperationException for a fully prevented qu…
pdevito3 Sep 30, 2026
76d3a7d
fix(filter): look up HasConversion by query name again
pdevito3 Sep 30, 2026
0f1d864
fix(filter): match a child collection member in the exact case again
pdevito3 Sep 30, 2026
f0f48be
fix(filter): replace query names before the parse again
pdevito3 Sep 30, 2026
5e7d918
fix(filter): resolve query names only in front of an operator again
pdevito3 Sep 30, 2026
8a09c25
fix(filter): skip the property depth check in arithmetic again
pdevito3 Sep 30, 2026
f5209e5
fix(filter): replace operator aliases before the parse again
pdevito3 Sep 30, 2026
01e8b50
fix(filter): split a list value on every comma again
pdevito3 Sep 30, 2026
7198ac2
fix(filter): keep the offset of a date time offset literal again
pdevito3 Sep 30, 2026
2fa061a
test(filter): give the filtered recipe a unique title
pdevito3 Sep 30, 2026
b49ad2b
fix(filter): read the zone before the fraction and drop a short quote…
pdevito3 Sep 30, 2026
0abd1f8
fix(operators): remove the null check from case-sensitive string oper…
pdevito3 Sep 30, 2026
0761e53
fix(operators): ignore usesAll in the operator factories again
pdevito3 Sep 30, 2026
e6d55b3
fix(operators): read a constant list in case-insensitive in and not-i…
pdevito3 Sep 30, 2026
19125d1
fix(operators): remove the obsolete mark from ArithmeticOperator.From…
pdevito3 Sep 30, 2026
22798f0
fix(operators): restore the v1.14.2 message for has on a non-collection
pdevito3 Sep 30, 2026
bc70b3a
fix(filter): resolve a derived property or custom operation query nam…
pdevito3 Sep 30, 2026
01b06c1
test: mark nullable property selectors in test configs as not null
pdevito3 Sep 30, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion QueryKit.IntegrationTests/Tests/DatabaseFilteringTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4301,7 +4301,7 @@ public async Task can_apply_query_kit_data()
SortOrder = "score desc",
Configuration = new QueryKitConfiguration(config =>
{
config.Property<Recipe>(x => x.Rating).HasQueryName("score");
config.Property<Recipe>(x => x.Rating!).HasQueryName("score");
})
};

Expand Down
29 changes: 15 additions & 14 deletions QueryKit.IntegrationTests/Tests/FilterParsingRegressionTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ namespace QueryKit.IntegrationTests.Tests;
public class FilterParsingRegressionTests : TestBase
{
[Fact]
public async Task operator_alias_text_inside_quoted_value_is_kept()
public async Task operator_alias_text_inside_quoted_value_is_replaced()
{
// Arrange
var testingServiceScope = new TestingServiceScope();
Expand All @@ -41,8 +41,7 @@ public async Task operator_alias_text_inside_quoted_value_is_kept()
var people = await appliedQueryable.ToListAsync();

// Assert
people.Count.Should().Be(1);
people[0].Id.Should().Be(fakePersonOne.Id);
people.Should().BeEmpty();
}

[Fact]
Expand Down Expand Up @@ -83,7 +82,7 @@ public async Task decimal_value_uses_invariant_culture()
}

[Fact]
public async Task list_value_with_comma_is_one_item()
public async Task list_value_with_comma_is_split_into_items()
{
// Arrange
var testingServiceScope = new TestingServiceScope();
Expand All @@ -107,8 +106,8 @@ public async Task list_value_with_comma_is_one_item()
var notInPeople = await queryablePeople.ApplyQueryKitFilter(notInInput).ToListAsync();

// Assert
inPeople.Select(x => x.Id).Should().Equal(fakePersonOne.Id);
notInPeople.Select(x => x.Id).Should().Equal(fakePersonTwo.Id);
inPeople.Select(x => x.Id).Should().Equal(fakePersonTwo.Id);
notInPeople.Select(x => x.Id).Should().Equal(fakePersonOne.Id);
}

[Theory]
Expand Down Expand Up @@ -143,11 +142,13 @@ public async Task date_time_offset_value_with_offset_matches_same_instant(string
}

[Theory]
[InlineData("SpecificDateTime == 2024-01-15T08:00:00.500Z")]
[InlineData("SpecificDate == 2024-01-15T10:00:00.5+02:00")]
[InlineData("Time == 08:30:00.5")]
[InlineData("Time == \"08:30:00.5\"")]
public async Task fractional_seconds_are_kept(string valueFilter)
[InlineData("SpecificDateTime == 2024-01-15T08:00:00.500Z", true)]
[InlineData("SpecificDateTime == 2024-01-15T08:00:00Z.5", true)]
[InlineData("SpecificDate == 2024-01-15T10:00:00.5+02:00", true)]
[InlineData("Time == 08:30:00.5", true)]
[InlineData("Time == \"08:30:00.500\"", true)]
[InlineData("Time == \"08:30:00.5\"", false)]
public async Task fractional_second_value_matches_by_its_fraction(string valueFilter, bool expectFractionPerson)
{
// Arrange
var testingServiceScope = new TestingServiceScope();
Expand All @@ -173,7 +174,7 @@ public async Task fractional_seconds_are_kept(string valueFilter)
var people = await queryablePeople.ApplyQueryKitFilter(input).ToListAsync();

// Assert
people.Select(x => x.Id).Should().Equal(fakePersonOne.Id);
people.Select(x => x.Id).Should().Equal(expectFractionPerson ? fakePersonOne.Id : fakePersonTwo.Id);
}

[Theory]
Expand Down Expand Up @@ -241,7 +242,7 @@ public async Task case_sensitive_string_operator_handles_null_property(string va
}

[Fact]
public async Task comparison_operator_factory_with_uses_all_matches_every_item()
public async Task comparison_operator_factory_with_uses_all_matches_any_item()
{
// Arrange
var testingServiceScope = new TestingServiceScope();
Expand All @@ -268,7 +269,7 @@ public async Task comparison_operator_factory_with_uses_all_matches_every_item()
.ToListAsync();

// Assert
recipes.Select(x => x.Id).Should().Equal(fakeRecipeOne.Id);
recipes.Select(x => x.Id).Should().BeEquivalentTo(new[] { fakeRecipeOne.Id, fakeRecipeTwo.Id });
}

[Fact]
Expand Down
149 changes: 0 additions & 149 deletions QueryKit.IntegrationTests/Tests/HasConversionTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,126 +41,6 @@ public async Task can_filter_by_email_with_has_conversion()
people[0].Id.Should().Be(person.Id);
}

[Fact]
public async Task can_filter_by_email_with_query_name_and_has_conversion()
{
// Arrange
var testingServiceScope = new TestingServiceScope();
var testEmail = $"{Guid.NewGuid()}@example.com";
var person = new FakeTestingPersonBuilder()
.WithEmail(testEmail)
.Build();
var personTwo = new FakeTestingPersonBuilder().Build();

await testingServiceScope.InsertAsync(person, personTwo);

var input = $"""mail == "{testEmail}" """;
var config = new QueryKitConfiguration(config =>
{
config.Property<TestingPerson>(x => x.Email).HasQueryName("mail").HasConversion<string>();
});

// Act
var queryablePeople = testingServiceScope.DbContext().People;
var appliedQueryable = queryablePeople.ApplyQueryKitFilter(input, config);
var people = await appliedQueryable.ToListAsync();

// Assert
people.Count.Should().Be(1);
people[0].Id.Should().Be(person.Id);
}

[Fact]
public async Task can_filter_by_email_property_path_when_query_name_and_has_conversion_are_configured()
{
// Arrange
var testingServiceScope = new TestingServiceScope();
var testEmail = $"{Guid.NewGuid()}@example.com";
var person = new FakeTestingPersonBuilder()
.WithEmail(testEmail)
.Build();
var personTwo = new FakeTestingPersonBuilder().Build();

await testingServiceScope.InsertAsync(person, personTwo);

var input = $"""Email == "{testEmail}" """;
var config = new QueryKitConfiguration(config =>
{
config.Property<TestingPerson>(x => x.Email).HasQueryName("mail").HasConversion<string>();
});

// Act
var queryablePeople = testingServiceScope.DbContext().People;
var appliedQueryable = queryablePeople.ApplyQueryKitFilter(input, config);
var people = await appliedQueryable.ToListAsync();

// Assert
people.Count.Should().Be(1);
people[0].Id.Should().Be(person.Id);
}

[Fact]
public async Task can_filter_by_email_value_with_query_name_and_has_conversion()
{
// Arrange
var testingServiceScope = new TestingServiceScope();
var testEmail = $"{Guid.NewGuid()}@example.com";
var person = new FakeTestingPersonBuilder()
.WithEmail(testEmail)
.Build();
var personTwo = new FakeTestingPersonBuilder().Build();

await testingServiceScope.InsertAsync(person, personTwo);

var input = $"""Email.Value == "{testEmail}" """;
var config = new QueryKitConfiguration(config =>
{
config.Property<TestingPerson>(x => x.Email).HasQueryName("mail").HasConversion<string>();
});

// Act
var queryablePeople = testingServiceScope.DbContext().People;
var appliedQueryable = queryablePeople.ApplyQueryKitFilter(input, config);
var people = await appliedQueryable.ToListAsync();

// Assert
people.Count.Should().Be(1);
people[0].Id.Should().Be(person.Id);
}

[Fact]
public async Task can_filter_by_null_email_with_query_name_and_has_conversion()
{
// Arrange
var testingServiceScope = new TestingServiceScope();
var title = Guid.NewGuid().ToString();
var person = new FakeTestingPersonBuilder()
.WithTitle(title)
.Build();
person.Email = null!;
var personTwo = new FakeTestingPersonBuilder()
.WithTitle(title)
.Build();

await testingServiceScope.InsertAsync(person, personTwo);

var input = """mail == null""";
var config = new QueryKitConfiguration(config =>
{
config.Property<TestingPerson>(x => x.Email).HasQueryName("mail").HasConversion<string>();
});

// Act
var queryablePeople = testingServiceScope.DbContext().People
.Where(x => x.Title == title);
var appliedQueryable = queryablePeople.ApplyQueryKitFilter(input, config);
var people = await appliedQueryable.ToListAsync();

// Assert
people.Count.Should().Be(1);
people[0].Id.Should().Be(person.Id);
}

[Fact]
public async Task can_filter_by_nested_postal_code_with_has_conversion()
{
Expand Down Expand Up @@ -190,35 +70,6 @@ public async Task can_filter_by_nested_postal_code_with_has_conversion()
people[0].Id.Should().Be(person.Id);
}

[Fact]
public async Task can_filter_by_nested_postal_code_with_query_name_and_has_conversion()
{
// Arrange
var testingServiceScope = new TestingServiceScope();
var postalCode = Guid.NewGuid().ToString("N")[..10];
var person = new FakeTestingPersonBuilder()
.WithPhysicalAddress(new Address("Line1", "Line2", "City", "State", postalCode, "Country"))
.Build();
var personTwo = new FakeTestingPersonBuilder().Build();

await testingServiceScope.InsertAsync(person, personTwo);

var input = $"""zip == "{postalCode}" """;
var config = new QueryKitConfiguration(config =>
{
config.Property<TestingPerson>(x => x.PhysicalAddress.PostalCode).HasQueryName("zip").HasConversion<string>();
});

// Act
var queryablePeople = testingServiceScope.DbContext().People;
var appliedQueryable = queryablePeople.ApplyQueryKitFilter(input, config);
var people = await appliedQueryable.ToListAsync();

// Assert
people.Count.Should().Be(1);
people[0].Id.Should().Be(person.Id);
}

[Fact]
public async Task can_filter_guid_with_contains_query_name_and_has_conversion()
{
Expand Down
Loading
Loading