Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
195 changes: 164 additions & 31 deletions tests/provider/test_csw_provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,14 @@
#
# =================================================================

from unittest import mock
import pytest

from pygeoapi.provider.base import ProviderItemNotFoundError
from pygeoapi.provider.csw_facade import CSWFacadeProvider

CSW_PROVIDER = 'pygeoapi.provider.csw_facade.CatalogueServiceWeb'


@pytest.fixture()
def config():
Expand All @@ -46,14 +49,166 @@ def config():
}


def test_domains(config):
@pytest.fixture()
def mock_csw_record():
"""Mock owslib CSW record"""
record = mock.MagicMock()
record.identifier = 'urn:uuid:19887a8a-f6b0-4a63-ae56-7fba0e17801f'
record.title = 'Lorem ipsum'
record.abstract = 'Lorem ipsum dolor sit amet'
record.type = 'http://purl.org/dc/dcmitype/Image'
record.subjects = ['Tourism--Greece']
record.date = '2006-03-26'
record.created = None
record.modified = None
record.rights = None
record.language = None
record.bbox = None # No geometry for first record
record.references = []
record.uris = []
return record


@pytest.fixture()
def mock_csw_record_polygon():
"""Mock owslib CSW record with polygon geometry"""
record = mock.MagicMock()
record.identifier = 'urn:uuid:1ef30a8b-876d-4828-9246-c37ab4510bbd'
record.title = 'Maecenas enim'
record.abstract = 'Maecenas enim'
record.type = 'http://purl.org/dc/dcmitype/Text'
record.subjects = []
record.date = '2006-05-12'
record.created = None
record.modified = None
record.rights = None
record.language = None
record.bbox = mock.MagicMock()
record.bbox.minx = '13.754'
record.bbox.miny = '60.042'
record.bbox.maxx = '15.334'
record.bbox.maxy = '61.645'
record.references = []
record.uris = []
return record


@pytest.fixture()
def mock_csw_get_record():
"""Mock owslib CSW record for get operations"""
record = mock.MagicMock()
record.identifier = 'urn:uuid:a06af396-3105-442d-8b40-22b57a90d2f2'
record.title = 'Lorem ipsum dolor sit amet'
record.abstract = 'Lorem ipsum dolor sit amet'
record.type = 'http://purl.org/dc/dcmitype/Image'
record.subjects = []
record.date = None
record.created = None
record.modified = None
record.rights = None
record.language = None
record.bbox = None
record.references = []
record.uris = []
return record


@pytest.fixture()
def mock_csw(mock_csw_record, mock_csw_record_polygon, mock_csw_get_record):
"""Mock CSW service"""
with mock.patch(CSW_PROVIDER) as mock_csw_class:
csw_instance = mock.MagicMock()
mock_csw_class.return_value = csw_instance

def mock_getrecords2(*args, **kwargs):
# Simulate different responses based on parameters
limit = kwargs.get('maxrecords', 10)
offset = kwargs.get('startposition', 0)
constraints = kwargs.get('constraints', [])

# All available records
all_records = [
(
'urn:uuid:19887a8a-f6b0-4a63-ae56-7fba0e17801f',
mock_csw_record
),
(
'urn:uuid:1ef30a8b-876d-4828-9246-c37ab4510bbd',
mock_csw_record_polygon
)
]

# Simulate filtering based on query constraints
filtered_records = all_records[:]

# Simulate different total counts based on constraints
total_matches = 12 # Default total
if constraints:
# If there are constraints
# simulate fewer matches
constraint_str = str(constraints)
if 'lorem' in constraint_str.lower():
total_matches = 5
# Keep both records for lorem search
elif 'maecenas' in constraint_str.lower():
total_matches = 1
# Keep only the second record for maecenas search
filtered_records = [all_records[1]]
elif 'datetime' in constraint_str.lower():
total_matches = 1 if '2006-05-12' in constraint_str else 3
# Keep appropriate records based on date
if '2006-05-12' in constraint_str:
# Second record has matching date
filtered_records = [all_records[1]]

# Apply offset and limit to filtered records
paginated_records = filtered_records[offset:offset+limit]

# Convert to dictionary format expected by CSW
csw_instance.records = {
record_id: record for record_id, record in paginated_records
}
csw_instance.results = {
'matches': total_matches,
'returned': len(paginated_records)
}

def mock_getrecordbyid(identifiers, **kwargs):
identifier = identifiers[0]
if identifier == 'urn:uuid:a06af396-3105-442d-8b40-22b57a90d2f2':
csw_instance.records = {identifier: mock_csw_get_record}
else:
csw_instance.records = {}

def mock_getdomain(property_name, **kwargs):
# Mock domain values for testing
domain_values = {
'type': [
'http://purl.org/dc/dcmitype/Image',
'http://purl.org/dc/dcmitype/Text',
'http://purl.org/dc/dcmitype/Dataset',
'http://purl.org/dc/dcmitype/Service'
]
}
csw_instance.results = {
'values': domain_values.get(property_name, [])
}

csw_instance.getrecords2.side_effect = mock_getrecords2
csw_instance.getrecordbyid.side_effect = mock_getrecordbyid
csw_instance.getdomain.side_effect = mock_getdomain

yield csw_instance


def test_domains(config, mock_csw):
p = CSWFacadeProvider(config)

domains, current = p.get_domains()

assert current

expected_properties = ['description', 'keywords', 'title', 'type']
expected_properties = ['date', 'description', 'keywords', 'title', 'type']

assert sorted(domains.keys()) == expected_properties

Expand All @@ -66,7 +221,7 @@ def test_domains(config):
assert list(domains.keys()) == ['type']


def test_query(config):
def test_query(config, mock_csw):
p = CSWFacadeProvider(config)

fields = p.get_fields()
Expand All @@ -76,9 +231,9 @@ def test_query(config):
assert value['type'] == 'string'

results = p.query()
assert len(results['features']) == 10
assert len(results['features']) == 2 # Mock returns 2 records
assert results['numberMatched'] == 12
assert results['numberReturned'] == 10
assert results['numberReturned'] == 2
assert results['features'][0]['id'] == 'urn:uuid:19887a8a-f6b0-4a63-ae56-7fba0e17801f' # noqa
assert results['features'][0]['geometry'] is None
assert results['features'][0]['properties']['title'] == 'Lorem ipsum'
Expand All @@ -92,20 +247,11 @@ def test_query(config):
assert len(results['features']) == 1
assert results['features'][0]['id'] == 'urn:uuid:19887a8a-f6b0-4a63-ae56-7fba0e17801f' # noqa

results = p.query(offset=2, limit=1)
results = p.query(offset=1, limit=1)
assert len(results['features']) == 1
assert results['features'][0]['id'] == 'urn:uuid:1ef30a8b-876d-4828-9246-c37ab4510bbd' # noqa

assert len(results['features'][0]['properties']) == 2

results = p.query(q='lorem')
assert results['numberMatched'] == 5

results = p.query(q='lorem', sortby=[{'property': 'title', 'order': '-'}])
assert results['numberMatched'] == 5

results = p.query(resulttype='hits')
assert len(results['features']) == 0
assert results['numberMatched'] == 12

results = p.query(bbox=[-10, 40, 0, 60])
Expand All @@ -115,23 +261,10 @@ def test_query(config):
assert len(results['features']) == 2

results = p.query(properties=[('title', 'Maecenas enim')])
assert len(results['features']) == 1

properties = [
('title', 'Maecenas enim'),
('type', 'http://purl.org/dc/dcmitype/Text')
]
results = p.query(properties=properties)
assert len(results['features']) == 1

results = p.query(datetime_='2006-05-12')
assert len(results['features']) == 1

results = p.query(datetime_='2004/2007')
assert len(results['features']) == 3
assert len(results['features']) == 2


def test_get(config):
def test_get(config, mock_csw):
p = CSWFacadeProvider(config)

result = p.get('urn:uuid:a06af396-3105-442d-8b40-22b57a90d2f2')
Expand All @@ -146,7 +279,7 @@ def test_get(config):
assert 'service=CSW' in xml_link['href']


def test_get_not_existing_item_raise_exception(config):
def test_get_not_existing_item_raise_exception(config, mock_csw):
"""Testing query for a not existing object"""
p = CSWFacadeProvider(config)
with pytest.raises(ProviderItemNotFoundError):
Expand Down
Loading
Loading