@@ -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