Skip to content

Commit 46be5e9

Browse files
committed
fix(filter)!: find HasConversion by the property path
v1.14.2 and main look up the HasConversion setting by query name after the alias pass replaced the query name with the property path. A property with both HasConversion and HasQueryName does not use its conversion, so a filter on it throws. The lookups use the property path. A null literal on a converted property compares against null. A converted nullable struct, Guid string operators, and property lists in another case use the conversion. BREAKING CHANGE: a property with HasConversion and HasQueryName now uses its conversion. Filters that threw now return rows. A null literal on a converted reference type matches null rows, not rows equal to a value built from the text null. A child path such as Email.Value on a converted parent compares the parent.
1 parent 365246a commit 46be5e9

4 files changed

Lines changed: 215 additions & 58 deletions

File tree

‎QueryKit.IntegrationTests/Tests/HasConversionTests.cs‎

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,126 @@ public async Task can_filter_by_email_with_has_conversion()
4141
people[0].Id.Should().Be(person.Id);
4242
}
4343

44+
[Fact]
45+
public async Task can_filter_by_email_with_query_name_and_has_conversion()
46+
{
47+
// Arrange
48+
var testingServiceScope = new TestingServiceScope();
49+
var testEmail = $"{Guid.NewGuid()}@example.com";
50+
var person = new FakeTestingPersonBuilder()
51+
.WithEmail(testEmail)
52+
.Build();
53+
var personTwo = new FakeTestingPersonBuilder().Build();
54+
55+
await testingServiceScope.InsertAsync(person, personTwo);
56+
57+
var input = $"""mail == "{testEmail}" """;
58+
var config = new QueryKitConfiguration(config =>
59+
{
60+
config.Property<TestingPerson>(x => x.Email).HasQueryName("mail").HasConversion<string>();
61+
});
62+
63+
// Act
64+
var queryablePeople = testingServiceScope.DbContext().People;
65+
var appliedQueryable = queryablePeople.ApplyQueryKitFilter(input, config);
66+
var people = await appliedQueryable.ToListAsync();
67+
68+
// Assert
69+
people.Count.Should().Be(1);
70+
people[0].Id.Should().Be(person.Id);
71+
}
72+
73+
[Fact]
74+
public async Task can_filter_by_email_property_path_when_query_name_and_has_conversion_are_configured()
75+
{
76+
// Arrange
77+
var testingServiceScope = new TestingServiceScope();
78+
var testEmail = $"{Guid.NewGuid()}@example.com";
79+
var person = new FakeTestingPersonBuilder()
80+
.WithEmail(testEmail)
81+
.Build();
82+
var personTwo = new FakeTestingPersonBuilder().Build();
83+
84+
await testingServiceScope.InsertAsync(person, personTwo);
85+
86+
var input = $"""Email == "{testEmail}" """;
87+
var config = new QueryKitConfiguration(config =>
88+
{
89+
config.Property<TestingPerson>(x => x.Email).HasQueryName("mail").HasConversion<string>();
90+
});
91+
92+
// Act
93+
var queryablePeople = testingServiceScope.DbContext().People;
94+
var appliedQueryable = queryablePeople.ApplyQueryKitFilter(input, config);
95+
var people = await appliedQueryable.ToListAsync();
96+
97+
// Assert
98+
people.Count.Should().Be(1);
99+
people[0].Id.Should().Be(person.Id);
100+
}
101+
102+
[Fact]
103+
public async Task can_filter_by_email_value_with_query_name_and_has_conversion()
104+
{
105+
// Arrange
106+
var testingServiceScope = new TestingServiceScope();
107+
var testEmail = $"{Guid.NewGuid()}@example.com";
108+
var person = new FakeTestingPersonBuilder()
109+
.WithEmail(testEmail)
110+
.Build();
111+
var personTwo = new FakeTestingPersonBuilder().Build();
112+
113+
await testingServiceScope.InsertAsync(person, personTwo);
114+
115+
var input = $"""Email.Value == "{testEmail}" """;
116+
var config = new QueryKitConfiguration(config =>
117+
{
118+
config.Property<TestingPerson>(x => x.Email).HasQueryName("mail").HasConversion<string>();
119+
});
120+
121+
// Act
122+
var queryablePeople = testingServiceScope.DbContext().People;
123+
var appliedQueryable = queryablePeople.ApplyQueryKitFilter(input, config);
124+
var people = await appliedQueryable.ToListAsync();
125+
126+
// Assert
127+
people.Count.Should().Be(1);
128+
people[0].Id.Should().Be(person.Id);
129+
}
130+
131+
[Fact]
132+
public async Task can_filter_by_null_email_with_query_name_and_has_conversion()
133+
{
134+
// Arrange
135+
var testingServiceScope = new TestingServiceScope();
136+
var title = Guid.NewGuid().ToString();
137+
var person = new FakeTestingPersonBuilder()
138+
.WithTitle(title)
139+
.Build();
140+
person.Email = null!;
141+
var personTwo = new FakeTestingPersonBuilder()
142+
.WithTitle(title)
143+
.Build();
144+
145+
await testingServiceScope.InsertAsync(person, personTwo);
146+
147+
var input = """mail == null""";
148+
var config = new QueryKitConfiguration(config =>
149+
{
150+
config.Property<TestingPerson>(x => x.Email).HasQueryName("mail").HasConversion<string>();
151+
});
152+
153+
// Act
154+
var queryablePeople = testingServiceScope.DbContext().People
155+
.Where(x => x.Title == title);
156+
var appliedQueryable = queryablePeople.ApplyQueryKitFilter(input, config);
157+
var people = await appliedQueryable.ToListAsync();
158+
159+
// Assert
160+
people.Count.Should().Be(1);
161+
people[0].Id.Should().Be(person.Id);
162+
}
163+
44164
[Fact]
45165
public async Task can_filter_by_nested_postal_code_with_has_conversion()
46166
{
@@ -70,6 +190,35 @@ public async Task can_filter_by_nested_postal_code_with_has_conversion()
70190
people[0].Id.Should().Be(person.Id);
71191
}
72192

193+
[Fact]
194+
public async Task can_filter_by_nested_postal_code_with_query_name_and_has_conversion()
195+
{
196+
// Arrange
197+
var testingServiceScope = new TestingServiceScope();
198+
var postalCode = Guid.NewGuid().ToString("N")[..10];
199+
var person = new FakeTestingPersonBuilder()
200+
.WithPhysicalAddress(new Address("Line1", "Line2", "City", "State", postalCode, "Country"))
201+
.Build();
202+
var personTwo = new FakeTestingPersonBuilder().Build();
203+
204+
await testingServiceScope.InsertAsync(person, personTwo);
205+
206+
var input = $"""zip == "{postalCode}" """;
207+
var config = new QueryKitConfiguration(config =>
208+
{
209+
config.Property<TestingPerson>(x => x.PhysicalAddress.PostalCode).HasQueryName("zip").HasConversion<string>();
210+
});
211+
212+
// Act
213+
var queryablePeople = testingServiceScope.DbContext().People;
214+
var appliedQueryable = queryablePeople.ApplyQueryKitFilter(input, config);
215+
var people = await appliedQueryable.ToListAsync();
216+
217+
// Assert
218+
people.Count.Should().Be(1);
219+
people[0].Id.Should().Be(person.Id);
220+
}
221+
73222
[Fact]
74223
public async Task can_filter_guid_with_contains_query_name_and_has_conversion()
75224
{

0 commit comments

Comments
 (0)