@@ -171,6 +171,31 @@ def test_eq_uuid(self):
171171 "accountid eq 12345678-1234-1234-1234-123456789abc" ,
172172 )
173173
174+ def test_eq_datetime (self ):
175+ dt = datetime (2024 , 1 , 15 , 10 , 30 , 0 , tzinfo = timezone .utc )
176+ self .assertEqual (
177+ eq ("createdon" , dt ).to_odata (),
178+ "createdon eq 2024-01-15T10:30:00Z" ,
179+ )
180+
181+ def test_eq_int_enum (self ):
182+ from enum import IntEnum
183+
184+ class Priority (IntEnum ):
185+ LOW = 1
186+ HIGH = 2
187+
188+ self .assertEqual (eq ("priority" , Priority .HIGH ).to_odata (), "priority eq 2" )
189+
190+ def test_ne_string (self ):
191+ self .assertEqual (ne ("name" , "Contoso" ).to_odata (), "name ne 'Contoso'" )
192+
193+ def test_gt_negative (self ):
194+ self .assertEqual (gt ("temperature" , - 10 ).to_odata (), "temperature gt -10" )
195+
196+ def test_gt_float (self ):
197+ self .assertEqual (gt ("revenue" , 99.5 ).to_odata (), "revenue gt 99.5" )
198+
174199
175200class TestFunctionFilters (unittest .TestCase ):
176201 """Tests for string function filter factory functions."""
@@ -187,6 +212,12 @@ def test_endswith(self):
187212 def test_function_column_lowercased (self ):
188213 self .assertEqual (contains ("Name" , "Corp" ).to_odata (), "contains(name, 'Corp')" )
189214
215+ def test_contains_single_quotes (self ):
216+ self .assertEqual (
217+ contains ("name" , "O'Brien" ).to_odata (),
218+ "contains(name, 'O''Brien')" ,
219+ )
220+
190221
191222class TestBetween (unittest .TestCase ):
192223 """Tests for the between factory function."""
@@ -201,6 +232,20 @@ def test_between_dates(self):
201232 result = between ("createdon" , date (2024 , 1 , 1 ), date (2024 , 12 , 31 )).to_odata ()
202233 self .assertEqual (result , "(createdon ge 2024-01-01 and createdon le 2024-12-31)" )
203234
235+ def test_between_floats (self ):
236+ self .assertEqual (
237+ between ("revenue" , 100.5 , 999.9 ).to_odata (),
238+ "(revenue ge 100.5 and revenue le 999.9)" ,
239+ )
240+
241+ def test_between_datetimes (self ):
242+ start = datetime (2024 , 1 , 1 , 0 , 0 , 0 , tzinfo = timezone .utc )
243+ end = datetime (2024 , 12 , 31 , 23 , 59 , 59 , tzinfo = timezone .utc )
244+ self .assertEqual (
245+ between ("createdon" , start , end ).to_odata (),
246+ "(createdon ge 2024-01-01T00:00:00Z and createdon le 2024-12-31T23:59:59Z)" ,
247+ )
248+
204249
205250class TestNullChecks (unittest .TestCase ):
206251 """Tests for is_null and is_not_null."""
@@ -234,31 +279,58 @@ class TestInFilter(unittest.TestCase):
234279 def test_filter_in_ints (self ):
235280 self .assertEqual (
236281 filter_in ("statecode" , [0 , 1 , 2 ]).to_odata (),
237- " Microsoft.Dynamics.CRM.In(PropertyName='statecode',PropertyValues=[0, 1, 2])" ,
282+ ' Microsoft.Dynamics.CRM.In(PropertyName=\ ' statecode\ ' ,PropertyValues=["0","1","2"])' ,
238283 )
239284
240285 def test_filter_in_strings (self ):
241286 self .assertEqual (
242287 filter_in ("name" , ["Contoso" , "Fabrikam" ]).to_odata (),
243- " Microsoft.Dynamics.CRM.In(PropertyName='name',PropertyValues=[' Contoso', ' Fabrikam'])" ,
288+ ' Microsoft.Dynamics.CRM.In(PropertyName=\ ' name\ ' ,PropertyValues=[" Contoso"," Fabrikam"])' ,
244289 )
245290
246291 def test_filter_in_single_value (self ):
247292 self .assertEqual (
248293 filter_in ("statecode" , [0 ]).to_odata (),
249- "Microsoft.Dynamics.CRM.In(PropertyName='statecode',PropertyValues=[0 ])" ,
294+ "Microsoft.Dynamics.CRM.In(PropertyName='statecode',PropertyValues=[\" 0 \" ])" ,
250295 )
251296
252297 def test_filter_in_column_lowercased (self ):
253298 self .assertEqual (
254299 filter_in ("StateCode" , [0 , 1 ]).to_odata (),
255- " Microsoft.Dynamics.CRM.In(PropertyName='statecode',PropertyValues=[0, 1])" ,
300+ ' Microsoft.Dynamics.CRM.In(PropertyName=\ ' statecode\ ' ,PropertyValues=["0","1"])' ,
256301 )
257302
258303 def test_filter_in_empty_raises (self ):
259304 with self .assertRaises (ValueError ):
260305 filter_in ("statecode" , [])
261306
307+ def test_filter_in_int_enum (self ):
308+ from enum import IntEnum
309+
310+ class Priority (IntEnum ):
311+ LOW = 1
312+ MEDIUM = 2
313+ HIGH = 3
314+
315+ self .assertEqual (
316+ filter_in ("priority" , [Priority .LOW , Priority .HIGH ]).to_odata (),
317+ 'Microsoft.Dynamics.CRM.In(PropertyName=\' priority\' ,PropertyValues=["1","3"])' ,
318+ )
319+
320+ def test_filter_in_strings_with_quotes (self ):
321+ self .assertEqual (
322+ filter_in ("name" , ["O'Brien" , "McDonald's" ]).to_odata (),
323+ "Microsoft.Dynamics.CRM.In(PropertyName='name',PropertyValues=[\" O'Brien\" ,\" McDonald's\" ])" ,
324+ )
325+
326+ def test_filter_in_uuids (self ):
327+ uid1 = uuid .UUID ("12345678-1234-1234-1234-123456789abc" )
328+ uid2 = uuid .UUID ("87654321-4321-4321-4321-cba987654321" )
329+ self .assertEqual (
330+ filter_in ("accountid" , [uid1 , uid2 ]).to_odata (),
331+ 'Microsoft.Dynamics.CRM.In(PropertyName=\' accountid\' ,PropertyValues=["12345678-1234-1234-1234-123456789abc","87654321-4321-4321-4321-cba987654321"])' ,
332+ )
333+
262334
263335class TestLogicalOperators (unittest .TestCase ):
264336 """Tests for &, |, ~ operator overloads."""
@@ -311,6 +383,13 @@ def test_or_with_non_expression_returns_not_implemented(self):
311383 result = eq ("a" , 1 ).__or__ ("not an expression" )
312384 self .assertIs (result , NotImplemented )
313385
386+ def test_and_with_filter_in (self ):
387+ expr = filter_in ("statecode" , [0 , 1 ]) & gt ("revenue" , 100000 )
388+ self .assertEqual (
389+ expr .to_odata (),
390+ '(Microsoft.Dynamics.CRM.In(PropertyName=\' statecode\' ,PropertyValues=["0","1"]) and revenue gt 100000)' ,
391+ )
392+
314393
315394class TestStrAndRepr (unittest .TestCase ):
316395 """Tests for __str__ and __repr__."""
0 commit comments