def test_query_overlapping_filter_keys(): gt_24 = expr.Comparison('age', expr.Gt(24)) lt_38 = expr.Comparison('age', expr.Lt(38)) compound1 = gt_24 & lt_38 compound2 = gt_24 & lt_38 query_filter = expr.Query(compound1, compound2).get_filter() assert query_filter == { '$and': [expr.query_expr(compound1), expr.query_expr(compound2)] }
def test_query_expr(): field_name = 'test' value = 'value' # If you pass in a dictionary it is just returned assert expr.query_expr({field_name: value}) == {field_name: value} with pytest.raises(TypeError): expr.query_expr([]) class FaultyFilterLike(expr.FilterLike): def __query_expr__(self) -> dict: return 'hello' with pytest.raises(TypeError): expr.query_expr(FaultyFilterLike())
def test_nested_fields(): assert expr.query_expr(Profile.thumbnail.width == 64) == { 'thumbnail.width': 64 } assert expr.query_expr(Profile.thumbnail == {'width': 64, 'height': 128}) == \ {'thumbnail': {'width': 64, 'height': 128}} # Add a query context tag_eq_holiday = fields.field('tag') == 'holiday' Profile.thumbnail.set_query_context(tag_eq_holiday) # check the query context is being used assert expr.query_expr(Profile.thumbnail == {'width': 64, 'height': 128}) == \ {'$and': [{'tag': 'holiday'}, {'thumbnail': {'width': 64, 'height': 128}}]} # now check that it is carried over to 'width' assert expr.query_expr(Profile.thumbnail.width == 64) == \ {'$and': [{'tag': 'holiday'}, {'thumbnail.width': 64}]}
def test_queryable(): """Test queryable operators result in MongoDB expressions that we expect""" field_name = 'test' value = 'value' list_value = 'val1', 'val2' class TestQueryable(expr.Queryable): field = field_name def get_path(self) -> str: return self.field queryable = TestQueryable() # Check that the field name cannot be None with pytest.raises(ValueError): queryable.field = None queryable == value queryable.field = field_name # Special case for equals which drops the operator assert expr.query_expr(queryable == value) == {field_name: value} # Check that 'simple' operators (i.e. field <op> value) simple_operators = { '__ne__': '$ne', '__gt__': '$gt', '__ge__': '$gte', '__lt__': '$lt', '__le__': '$lte', } for attr, op in simple_operators.items(): query_expr = expr.query_expr(getattr(queryable, attr)(value)) assert query_expr == {field_name: {op: value}} # Check operators that take a list of values list_operators = { 'in_': '$in', 'nin_': '$nin', } for attr, op in list_operators.items(): query_expr = expr.query_expr(getattr(queryable, attr)(*list_value)) assert query_expr == {field_name: {op: list_value}} # Test exists assert expr.query_expr(queryable.exists_(True)) == { field_name: { '$exists': True } } with pytest.raises(ValueError): expr.query_expr(queryable.exists_('true')) # Test regex assert expr.query_expr(queryable.regex_(value)) == { field_name: { '$regex': value } } assert expr.query_expr(queryable.regex_(value, 'i')) == { field_name: { '$regex': value, '$options': 'i' } } with pytest.raises(ValueError): queryable.regex_(True) # Test starts_with assert expr.query_expr(queryable.starts_with_(value)) == { field_name: { '$regex': f'^{value}' } }