def test_SearchQuery_from_is_calculated_from_page_and_page_size(): """The 'from' value in SearchQuery's JSON is calculated properly""" params = types.ItemsQueryType() sq1 = search_query.SearchQuery(params) assert sq1.query['from'] == 0 params = types.ItemsQueryType({'page': '2', 'page_size': '2'}) sq2 = search_query.SearchQuery(params) assert sq2.query['from'] == 2
def test_query_string_clause_has_all_correct_fields_for_q_query(): """A 'q=' query hits all of the correct fields w field boosts""" params = types.ItemsQueryType({'q': 'test'}) sq = search_query.SearchQuery(params) good_fields = [ 'sourceResource.title^2', 'sourceResource.description^0.75', 'sourceResource.collection.title^1', 'sourceResource.collection.description^1', 'sourceResource.contributor^1', 'sourceResource.creator^1', 'sourceResource.extent^1', 'sourceResource.format^1', 'sourceResource.language.name^1', 'sourceResource.publisher^1', 'sourceResource.relation^1', 'sourceResource.rights^1', 'sourceResource.spatial.country^0.75', 'sourceResource.spatial.county^1', 'sourceResource.spatial.name^1', 'sourceResource.spatial.region^1', 'sourceResource.spatial.state^0.75', 'sourceResource.specType^1', 'sourceResource.subject.name^1', 'sourceResource.type^1', 'dataProvider^1', 'intermediateProvider^1', 'provider.name^1', ] got_fields = sq.query['query']['bool']['must'][0]['query_string']['fields'] assert sorted(got_fields) == sorted(good_fields)
def test_ItemsQueryType_truncates_page_size(): """ItemsQueryType truncates a page_size greater than 500 to 500 This is not ideal, but it's what the API has always done. """ x = types.ItemsQueryType({'page_size': '501'}) assert x['page_size'] == 500
def test_SearchQuery_add_range_clause_after(): params = types.ItemsQueryType({'sourceResource.date.after': '2000'}) sq = search_query.SearchQuery(params) assert sq.query['query']['bool']['must'][0] == { 'range': { 'sourceResource.date.end': { 'gte': '2000' } } }
def test_SearchQuery_has_sort_given_sort_by_param(): """The search query has the correct sort if we got a sort_by parameter""" params = types.ItemsQueryType({'sort_by': 'sourceResource.type'}) sq = search_query.SearchQuery(params) assert sq.query['sort'] == [{ 'sourceResource.type': { 'order': 'asc' } }, { '_score': { 'order': 'desc' } }]
def test_SearchQuery_does_geo_distance_sort(): """A _geo_distance sort is performed for coordinates and pin params""" params = types.ItemsQueryType({ 'sort_by': 'sourceResource.spatial.coordinates', 'sort_by_pin': '26.15952,-97.99084' }) sq = search_query.SearchQuery(params) assert sq.query['sort'] == [{ '_geo_distance': { 'sourceResource.spatial.coordinates': '26.15952,-97.99084', 'order': 'asc', 'unit': 'mi' } }]
def test_SearchQuery_uses_not_analyzed_field_where_necessary(): """The search query specifies the not_analyzed (keyword) field if the requested fields needs it; usually when it's a text field.""" params = types.ItemsQueryType({'sort_by': 'sourceResource.title'}) sq = search_query.SearchQuery(params) assert sq.query['sort'] == [{ 'sourceResource.title.not_analyzed': { 'order': 'asc' } }, { '_score': { 'order': 'desc' } }]
def test_SearchQuery_has_correct_default_sort(): """The search query without sort requested has the correct 'sort'""" params = types.ItemsQueryType() sq = search_query.SearchQuery(params) assert sq.query['sort'] == [ { '_score': { 'order': 'desc' } }, { 'id': { 'order': 'asc' } }, ]
def test_ItemsQueryType_sets_default_sort_order(): """ItemsQueryType sets sort_order if it is not given""" x = types.ItemsQueryType() assert x['sort_order'] == 'asc'
def test_SearchQuery_produces_bool_query_for_query_terms(): """SearchQuery produces 'bool' syntax if there are search terms""" params = types.ItemsQueryType({'q': 'test'}) sq = search_query.SearchQuery(params) assert 'bool' in sq.query['query'] assert 'match_all' not in sq.query['query']
def test_ItemsQueryType_flunks_bad_string_pattern(): """ItemsQueryType flunks a field that has the wrong pattern""" # In this case, the field is supposed to be a URL with pytest.raises(ValidationError): types.ItemsQueryType({'rights': "I'm free!"})
def test_ItemsQueryType_flunks_bad_string_length(): """ItemsQueryType flunks a field that is the wrong length""" # Just one sample field of many with pytest.raises(ValidationError): types.ItemsQueryType({'q': 'x'}) # Too few characters
def test_SearchQuery_can_handle_match_all_and_fields(): """A correct ES query is generated for a match_all() with a _source prop""" params = types.ItemsQueryType({'fields': 'id'}) sq = search_query.SearchQuery(params) assert 'match_all' in str(sq.query) assert '_source' in sq.query
def test_ItemsQueryType_passes_good_string_pattern(): """ItemsQueryType passes a field that has the correct pattern""" # Again, the field is supposed to be a URL assert types.ItemsQueryType({ 'rights': "http://rightsstatements.org/vocab/InC/1.0/"})
def test_ItemsQueryType_flunks_bad_param_name(): """ItemsQueryType flunks a bad querystring parameter name""" with pytest.raises(ValidationError): types.ItemsQueryType({'not_a_valid_param': 'x'})
def test_ItemsQueryType_validates_page_number(): """ItemsQueryType validates that page and page size are within limits""" types.ItemsQueryType({'page_size': '500', 'page': '100'}) # OK with pytest.raises(ValidationError): types.ItemsQueryType({'page_size': '500', 'page': '101'})
def test_ItemsQueryType_sets_default_page(): """ItemsQueryType sets default page number 1 if it is not provided""" x = types.ItemsQueryType() assert x['page'] == 1
def test_ItemsQueryType_sets_default_page_size(): """ItemsQueryType sets default page size 10 if it is not provided""" x = types.ItemsQueryType() assert x['page_size'] == 10
def test_ItemsQueryType_can_be_instantiated(): """ItemsQueryType can be instantiated with a dict without error""" assert types.ItemsQueryType({'q': 'xx'})
def test_ItemsQueryType_flunks_sort_on_coordinates_without_pin(): """ItemsQueryType fails a sort on sourceResource.spatial.coordinates without a sort_by_pin value""" with pytest.raises(ValidationError): types.ItemsQueryType({'sort_by': 'sourceResource.spatial.coordinates'})
def test_SearchQuery_adds_facets_to_query(): """SearchQuery adds a 'facets' property to the query if a 'facets' param is given.""" params = types.ItemsQueryType({'facets': 'provider.name'}) sq = search_query.SearchQuery(params) assert 'aggs' in sq.query
def test_SearchQuery_produces_match_all_for_no_query_terms(): """SearchQuery produces 'match_all' syntax if there are no search terms""" params = types.ItemsQueryType() sq = search_query.SearchQuery(params) assert 'match_all' in str(sq.query) assert 'bool' in sq.query['query']
def test_SearchQuery_has_source_clause_for_fields_constraint(): """If there's a "fields" query param, there's a "_source" property in the Elasticsearch query.""" params = types.ItemsQueryType({'fields': 'id'}) sq = search_query.SearchQuery(params) assert '_source' in sq.query
def test_SearchQuery_has_size_and_from(): """The JSON generated by SearchQuery has 'size' and 'from' properties.""" params = types.ItemsQueryType() sq = search_query.SearchQuery(params) assert 'size' in sq.query assert 'from' in sq.query
def test_SearchQuery_can_handle_bool_and_fields(): """A correct ES query is generated for a bool with a _source prop""" params = types.ItemsQueryType({'provider.name': 'test', 'fields': 'id'}) sq = search_query.SearchQuery(params) assert 'bool' in sq.query['query'] assert '_source' in sq.query
def test_an_ItemsQueryType_object_is_a_dict(): """ItemsQueryType extends dict""" x = types.ItemsQueryType({'q': 'xx'}) assert isinstance(x, dict)