Skip to content

Commit 9051630

Browse files
committed
feat: can compare properties
resolves #59
1 parent a9db41c commit 9051630

File tree

3 files changed

+447
-4
lines changed

3 files changed

+447
-4
lines changed

QueryKit.IntegrationTests/Tests/DatabaseFilteringTests.cs

Lines changed: 259 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,14 +162,17 @@ public async Task can_filter_by_and_also_bool()
162162
{
163163
// Arrange
164164
var testingServiceScope = new TestingServiceScope();
165+
var faker = new Faker();
166+
var uniqueTitle = faker.Lorem.Sentence();
165167
var fakePersonOne = new FakeTestingPersonBuilder()
166168
.WithFirstName("John")
167169
.WithAge(18)
170+
.WithTitle(uniqueTitle)
168171
.Build();
169172
var fakePersonTwo = new FakeTestingPersonBuilder().Build();
170173
await testingServiceScope.InsertAsync(fakePersonOne, fakePersonTwo);
171174

172-
var input = $"""adult_johns == true""";
175+
var input = $"""adult_johns == true && Title == "{uniqueTitle}" """;
173176
var config = new QueryKitConfiguration(config =>
174177
{
175178
config.DerivedProperty<TestingPerson>(tp => tp.Age >= 18 && tp.FirstName == "John").HasQueryName("adult_johns");
@@ -1769,4 +1772,259 @@ public async Task can_filter_on_db_sequence_as_child()
17691772
people.FirstOrDefault(x => x.Id == fakeRecipeOne.Id).Should().NotBeNull();
17701773
people.FirstOrDefault(x => x.Id == fakeRecipeTwo.Id).Should().BeNull();
17711774
}
1775+
1776+
[Fact]
1777+
public async Task can_filter_with_property_to_property_string_comparison()
1778+
{
1779+
// Arrange
1780+
var testingServiceScope = new TestingServiceScope();
1781+
var faker = new Faker();
1782+
1783+
var fakePersonOne = new FakeTestingPersonBuilder()
1784+
.WithFirstName("John")
1785+
.WithLastName("John")
1786+
.WithTitle(faker.Lorem.Sentence())
1787+
.Build();
1788+
1789+
var fakePersonTwo = new FakeTestingPersonBuilder()
1790+
.WithFirstName("Jane")
1791+
.WithLastName("Doe")
1792+
.WithTitle(faker.Lorem.Sentence())
1793+
.Build();
1794+
1795+
await testingServiceScope.InsertAsync(fakePersonOne, fakePersonTwo);
1796+
1797+
var input = $"""FirstName == LastName && Title == "{fakePersonOne.Title}" """;
1798+
1799+
// Act
1800+
var queryablePeople = testingServiceScope.DbContext().People;
1801+
var appliedQueryable = queryablePeople.ApplyQueryKitFilter(input);
1802+
var people = await appliedQueryable.ToListAsync();
1803+
1804+
// Assert
1805+
people.Count.Should().Be(1);
1806+
people[0].Id.Should().Be(fakePersonOne.Id);
1807+
people[0].FirstName.Should().Be(people[0].LastName);
1808+
}
1809+
1810+
[Fact]
1811+
public async Task can_filter_with_property_to_property_numeric_comparison()
1812+
{
1813+
// Arrange
1814+
var testingServiceScope = new TestingServiceScope();
1815+
var faker = new Faker();
1816+
1817+
var fakePersonOne = new FakeTestingPersonBuilder()
1818+
.WithAge(25)
1819+
.WithRating(20.5m)
1820+
.WithTitle(faker.Lorem.Sentence())
1821+
.Build();
1822+
1823+
var fakePersonTwo = new FakeTestingPersonBuilder()
1824+
.WithAge(30)
1825+
.WithRating(35.0m)
1826+
.WithTitle(faker.Lorem.Sentence())
1827+
.Build();
1828+
1829+
await testingServiceScope.InsertAsync(fakePersonOne, fakePersonTwo);
1830+
1831+
var input = $"""Age > Rating && Title == "{fakePersonOne.Title}" """;
1832+
1833+
// Act
1834+
var queryablePeople = testingServiceScope.DbContext().People;
1835+
var appliedQueryable = queryablePeople.ApplyQueryKitFilter(input);
1836+
var people = await appliedQueryable.ToListAsync();
1837+
1838+
// Assert
1839+
people.Count.Should().Be(1);
1840+
people[0].Id.Should().Be(fakePersonOne.Id);
1841+
people[0].Age.Should().BeGreaterThan((int)people[0].Rating!.Value);
1842+
}
1843+
1844+
[Fact]
1845+
public async Task can_filter_with_property_to_property_different_operators()
1846+
{
1847+
// Arrange
1848+
var testingServiceScope = new TestingServiceScope();
1849+
var faker = new Faker();
1850+
1851+
var fakePersonOne = new FakeTestingPersonBuilder()
1852+
.WithFirstName("Alice")
1853+
.WithLastName("Bob")
1854+
.WithAge(25)
1855+
.WithRating(20.5m)
1856+
.WithTitle(faker.Lorem.Sentence())
1857+
.Build();
1858+
1859+
await testingServiceScope.InsertAsync(fakePersonOne);
1860+
1861+
var input = $"""FirstName != LastName && Age > Rating && Title == "{fakePersonOne.Title}" """;
1862+
1863+
// Act
1864+
var queryablePeople = testingServiceScope.DbContext().People;
1865+
var appliedQueryable = queryablePeople.ApplyQueryKitFilter(input);
1866+
var people = await appliedQueryable.ToListAsync();
1867+
1868+
// Assert
1869+
people.Count.Should().Be(1);
1870+
people[0].Id.Should().Be(fakePersonOne.Id);
1871+
people[0].FirstName.Should().NotBe(people[0].LastName);
1872+
people[0].Age.Should().BeGreaterThan((int)people[0].Rating!.Value);
1873+
}
1874+
1875+
[Fact]
1876+
public async Task can_filter_with_property_to_property_combined_with_literal_values()
1877+
{
1878+
// Arrange
1879+
var testingServiceScope = new TestingServiceScope();
1880+
var faker = new Faker();
1881+
1882+
var fakePersonOne = new FakeTestingPersonBuilder()
1883+
.WithFirstName("John")
1884+
.WithLastName("John")
1885+
.WithAge(25)
1886+
.WithTitle(faker.Lorem.Sentence())
1887+
.Build();
1888+
1889+
var fakePersonTwo = new FakeTestingPersonBuilder()
1890+
.WithFirstName("Jane")
1891+
.WithLastName("Doe")
1892+
.WithAge(18)
1893+
.WithTitle(faker.Lorem.Sentence())
1894+
.Build();
1895+
1896+
await testingServiceScope.InsertAsync(fakePersonOne, fakePersonTwo);
1897+
1898+
var input = $"""FirstName == LastName && Age > 21 && Title == "{fakePersonOne.Title}" """;
1899+
1900+
// Act
1901+
var queryablePeople = testingServiceScope.DbContext().People;
1902+
var appliedQueryable = queryablePeople.ApplyQueryKitFilter(input);
1903+
var people = await appliedQueryable.ToListAsync();
1904+
1905+
// Assert - Only fakePersonOne matches both conditions
1906+
people.Count.Should().Be(1);
1907+
people[0].Id.Should().Be(fakePersonOne.Id);
1908+
people[0].FirstName.Should().Be(people[0].LastName);
1909+
people[0].Age.Should().BeGreaterThan(21);
1910+
}
1911+
1912+
[Fact]
1913+
public async Task can_filter_with_property_to_property_child_properties()
1914+
{
1915+
// Arrange
1916+
var testingServiceScope = new TestingServiceScope();
1917+
var faker = new Faker();
1918+
1919+
var matchingName = "TestAuthor123";
1920+
var fakeAuthor = new FakeAuthorBuilder()
1921+
.WithName(matchingName)
1922+
.Build();
1923+
1924+
var fakeRecipe = new FakeRecipeBuilder()
1925+
.WithTitle(matchingName) // Same as author name
1926+
.Build();
1927+
fakeRecipe.SetAuthor(fakeAuthor);
1928+
1929+
var differentAuthor = new FakeAuthorBuilder()
1930+
.WithName("DifferentAuthor")
1931+
.Build();
1932+
1933+
var differentRecipe = new FakeRecipeBuilder()
1934+
.WithTitle("DifferentTitle")
1935+
.Build();
1936+
differentRecipe.SetAuthor(differentAuthor);
1937+
1938+
await testingServiceScope.InsertAsync(fakeRecipe, differentRecipe);
1939+
1940+
var input = """Author.Name == Title""";
1941+
1942+
// Act
1943+
var queryableRecipes = testingServiceScope.DbContext().Recipes
1944+
.Include(x => x.Author);
1945+
var appliedQueryable = queryableRecipes.ApplyQueryKitFilter(input);
1946+
var recipes = await appliedQueryable.ToListAsync();
1947+
1948+
// Assert
1949+
recipes.Count.Should().Be(1);
1950+
recipes[0].Id.Should().Be(fakeRecipe.Id);
1951+
recipes[0].Author.Name.Should().Be(recipes[0].Title);
1952+
}
1953+
1954+
[Fact]
1955+
public async Task can_filter_with_property_to_property_child_property_with_nested_access()
1956+
{
1957+
// Arrange
1958+
var testingServiceScope = new TestingServiceScope();
1959+
var faker = new Faker();
1960+
1961+
var matchingValue = "[email protected]";
1962+
var fakeRecipe = new FakeRecipeBuilder()
1963+
.WithTitle(matchingValue)
1964+
.WithCollectionEmail(matchingValue) // Recipe.CollectionEmail.Value should equal Recipe.Title
1965+
.Build();
1966+
1967+
var differentRecipe = new FakeRecipeBuilder()
1968+
.WithTitle("different-title")
1969+
.WithCollectionEmail("[email protected]")
1970+
.Build();
1971+
1972+
await testingServiceScope.InsertAsync(fakeRecipe, differentRecipe);
1973+
1974+
var input = """CollectionEmail.Value == Title""";
1975+
1976+
// Act
1977+
var queryableRecipes = testingServiceScope.DbContext().Recipes;
1978+
var appliedQueryable = queryableRecipes.ApplyQueryKitFilter(input);
1979+
var recipes = await appliedQueryable.ToListAsync();
1980+
1981+
// Assert
1982+
recipes.Count.Should().Be(1);
1983+
recipes[0].Id.Should().Be(fakeRecipe.Id);
1984+
recipes[0].CollectionEmail.Value.Should().Be(recipes[0].Title);
1985+
}
1986+
1987+
[Fact]
1988+
public async Task can_filter_with_property_to_property_mixed_child_and_root_properties()
1989+
{
1990+
// Arrange
1991+
var testingServiceScope = new TestingServiceScope();
1992+
var faker = new Faker();
1993+
1994+
var authorName = "TestAuthor";
1995+
var rating = 5;
1996+
1997+
var fakeAuthor = new FakeAuthorBuilder()
1998+
.WithName(authorName)
1999+
.Build();
2000+
2001+
var fakeRecipe = new FakeRecipeBuilder()
2002+
.WithTitle("SomeTitle")
2003+
.WithRating(rating)
2004+
.Build();
2005+
fakeRecipe.SetAuthor(fakeAuthor);
2006+
2007+
// Add a test person with matching values
2008+
var fakePerson = new FakeTestingPersonBuilder()
2009+
.WithFirstName(authorName) // Person.FirstName == Recipe.Author.Name
2010+
.WithAge(rating) // Person.Age == Recipe.Rating
2011+
.WithTitle(faker.Lorem.Sentence())
2012+
.Build();
2013+
2014+
await testingServiceScope.InsertAsync(fakeRecipe);
2015+
await testingServiceScope.InsertAsync(fakePerson);
2016+
2017+
var input = $"""FirstName == "{authorName}" && Age == {rating} && Title == "{fakePerson.Title}" """;
2018+
2019+
// Act
2020+
var queryablePeople = testingServiceScope.DbContext().People;
2021+
var appliedQueryable = queryablePeople.ApplyQueryKitFilter(input);
2022+
var people = await appliedQueryable.ToListAsync();
2023+
2024+
// Assert
2025+
people.Count.Should().Be(1);
2026+
people[0].Id.Should().Be(fakePerson.Id);
2027+
people[0].FirstName.Should().Be(authorName);
2028+
people[0].Age.Should().Be(rating);
2029+
}
17722030
}

0 commit comments

Comments
 (0)