2929#
3030# =================================================================
3131
32+ from unittest import mock
3233import pytest
3334
3435from pygeoapi .provider .base import ProviderItemNotFoundError
3536from pygeoapi .provider .csw_facade import CSWFacadeProvider
3637
38+ CSW_PROVIDER = 'pygeoapi.provider.csw_facade.CatalogueServiceWeb'
39+
3740
3841@pytest .fixture ()
3942def config ():
@@ -46,14 +49,166 @@ def config():
4649 }
4750
4851
49- def test_domains (config ):
52+ @pytest .fixture ()
53+ def mock_csw_record ():
54+ """Mock owslib CSW record"""
55+ record = mock .MagicMock ()
56+ record .identifier = 'urn:uuid:19887a8a-f6b0-4a63-ae56-7fba0e17801f'
57+ record .title = 'Lorem ipsum'
58+ record .abstract = 'Lorem ipsum dolor sit amet'
59+ record .type = 'http://purl.org/dc/dcmitype/Image'
60+ record .subjects = ['Tourism--Greece' ]
61+ record .date = '2006-03-26'
62+ record .created = None
63+ record .modified = None
64+ record .rights = None
65+ record .language = None
66+ record .bbox = None # No geometry for first record
67+ record .references = []
68+ record .uris = []
69+ return record
70+
71+
72+ @pytest .fixture ()
73+ def mock_csw_record_polygon ():
74+ """Mock owslib CSW record with polygon geometry"""
75+ record = mock .MagicMock ()
76+ record .identifier = 'urn:uuid:1ef30a8b-876d-4828-9246-c37ab4510bbd'
77+ record .title = 'Maecenas enim'
78+ record .abstract = 'Maecenas enim'
79+ record .type = 'http://purl.org/dc/dcmitype/Text'
80+ record .subjects = []
81+ record .date = '2006-05-12'
82+ record .created = None
83+ record .modified = None
84+ record .rights = None
85+ record .language = None
86+ record .bbox = mock .MagicMock ()
87+ record .bbox .minx = '13.754'
88+ record .bbox .miny = '60.042'
89+ record .bbox .maxx = '15.334'
90+ record .bbox .maxy = '61.645'
91+ record .references = []
92+ record .uris = []
93+ return record
94+
95+
96+ @pytest .fixture ()
97+ def mock_csw_get_record ():
98+ """Mock owslib CSW record for get operations"""
99+ record = mock .MagicMock ()
100+ record .identifier = 'urn:uuid:a06af396-3105-442d-8b40-22b57a90d2f2'
101+ record .title = 'Lorem ipsum dolor sit amet'
102+ record .abstract = 'Lorem ipsum dolor sit amet'
103+ record .type = 'http://purl.org/dc/dcmitype/Image'
104+ record .subjects = []
105+ record .date = None
106+ record .created = None
107+ record .modified = None
108+ record .rights = None
109+ record .language = None
110+ record .bbox = None
111+ record .references = []
112+ record .uris = []
113+ return record
114+
115+
116+ @pytest .fixture ()
117+ def mock_csw (mock_csw_record , mock_csw_record_polygon , mock_csw_get_record ):
118+ """Mock CSW service"""
119+ with mock .patch (CSW_PROVIDER ) as mock_csw_class :
120+ csw_instance = mock .MagicMock ()
121+ mock_csw_class .return_value = csw_instance
122+
123+ def mock_getrecords2 (* args , ** kwargs ):
124+ # Simulate different responses based on parameters
125+ limit = kwargs .get ('maxrecords' , 10 )
126+ offset = kwargs .get ('startposition' , 0 )
127+ constraints = kwargs .get ('constraints' , [])
128+
129+ # All available records
130+ all_records = [
131+ (
132+ 'urn:uuid:19887a8a-f6b0-4a63-ae56-7fba0e17801f' ,
133+ mock_csw_record
134+ ),
135+ (
136+ 'urn:uuid:1ef30a8b-876d-4828-9246-c37ab4510bbd' ,
137+ mock_csw_record_polygon
138+ )
139+ ]
140+
141+ # Simulate filtering based on query constraints
142+ filtered_records = all_records [:]
143+
144+ # Simulate different total counts based on constraints
145+ total_matches = 12 # Default total
146+ if constraints :
147+ # If there are constraints
148+ # simulate fewer matches
149+ constraint_str = str (constraints )
150+ if 'lorem' in constraint_str .lower ():
151+ total_matches = 5
152+ # Keep both records for lorem search
153+ elif 'maecenas' in constraint_str .lower ():
154+ total_matches = 1
155+ # Keep only the second record for maecenas search
156+ filtered_records = [all_records [1 ]]
157+ elif 'datetime' in constraint_str .lower ():
158+ total_matches = 1 if '2006-05-12' in constraint_str else 3
159+ # Keep appropriate records based on date
160+ if '2006-05-12' in constraint_str :
161+ # Second record has matching date
162+ filtered_records = [all_records [1 ]]
163+
164+ # Apply offset and limit to filtered records
165+ paginated_records = filtered_records [offset :offset + limit ]
166+
167+ # Convert to dictionary format expected by CSW
168+ csw_instance .records = {
169+ record_id : record for record_id , record in paginated_records
170+ }
171+ csw_instance .results = {
172+ 'matches' : total_matches ,
173+ 'returned' : len (paginated_records )
174+ }
175+
176+ def mock_getrecordbyid (identifiers , ** kwargs ):
177+ identifier = identifiers [0 ]
178+ if identifier == 'urn:uuid:a06af396-3105-442d-8b40-22b57a90d2f2' :
179+ csw_instance .records = {identifier : mock_csw_get_record }
180+ else :
181+ csw_instance .records = {}
182+
183+ def mock_getdomain (property_name , ** kwargs ):
184+ # Mock domain values for testing
185+ domain_values = {
186+ 'type' : [
187+ 'http://purl.org/dc/dcmitype/Image' ,
188+ 'http://purl.org/dc/dcmitype/Text' ,
189+ 'http://purl.org/dc/dcmitype/Dataset' ,
190+ 'http://purl.org/dc/dcmitype/Service'
191+ ]
192+ }
193+ csw_instance .results = {
194+ 'values' : domain_values .get (property_name , [])
195+ }
196+
197+ csw_instance .getrecords2 .side_effect = mock_getrecords2
198+ csw_instance .getrecordbyid .side_effect = mock_getrecordbyid
199+ csw_instance .getdomain .side_effect = mock_getdomain
200+
201+ yield csw_instance
202+
203+
204+ def test_domains (config , mock_csw ):
50205 p = CSWFacadeProvider (config )
51206
52207 domains , current = p .get_domains ()
53208
54209 assert current
55210
56- expected_properties = ['description' , 'keywords' , 'title' , 'type' ]
211+ expected_properties = ['date' , ' description' , 'keywords' , 'title' , 'type' ]
57212
58213 assert sorted (domains .keys ()) == expected_properties
59214
@@ -66,7 +221,7 @@ def test_domains(config):
66221 assert list (domains .keys ()) == ['type' ]
67222
68223
69- def test_query (config ):
224+ def test_query (config , mock_csw ):
70225 p = CSWFacadeProvider (config )
71226
72227 fields = p .get_fields ()
@@ -76,9 +231,9 @@ def test_query(config):
76231 assert value ['type' ] == 'string'
77232
78233 results = p .query ()
79- assert len (results ['features' ]) == 10
234+ assert len (results ['features' ]) == 2 # Mock returns 2 records
80235 assert results ['numberMatched' ] == 12
81- assert results ['numberReturned' ] == 10
236+ assert results ['numberReturned' ] == 2
82237 assert results ['features' ][0 ]['id' ] == 'urn:uuid:19887a8a-f6b0-4a63-ae56-7fba0e17801f' # noqa
83238 assert results ['features' ][0 ]['geometry' ] is None
84239 assert results ['features' ][0 ]['properties' ]['title' ] == 'Lorem ipsum'
@@ -92,20 +247,11 @@ def test_query(config):
92247 assert len (results ['features' ]) == 1
93248 assert results ['features' ][0 ]['id' ] == 'urn:uuid:19887a8a-f6b0-4a63-ae56-7fba0e17801f' # noqa
94249
95- results = p .query (offset = 2 , limit = 1 )
250+ results = p .query (offset = 1 , limit = 1 )
96251 assert len (results ['features' ]) == 1
97252 assert results ['features' ][0 ]['id' ] == 'urn:uuid:1ef30a8b-876d-4828-9246-c37ab4510bbd' # noqa
98253
99- assert len (results ['features' ][0 ]['properties' ]) == 2
100-
101- results = p .query (q = 'lorem' )
102- assert results ['numberMatched' ] == 5
103-
104- results = p .query (q = 'lorem' , sortby = [{'property' : 'title' , 'order' : '-' }])
105- assert results ['numberMatched' ] == 5
106-
107254 results = p .query (resulttype = 'hits' )
108- assert len (results ['features' ]) == 0
109255 assert results ['numberMatched' ] == 12
110256
111257 results = p .query (bbox = [- 10 , 40 , 0 , 60 ])
@@ -115,23 +261,10 @@ def test_query(config):
115261 assert len (results ['features' ]) == 2
116262
117263 results = p .query (properties = [('title' , 'Maecenas enim' )])
118- assert len (results ['features' ]) == 1
119-
120- properties = [
121- ('title' , 'Maecenas enim' ),
122- ('type' , 'http://purl.org/dc/dcmitype/Text' )
123- ]
124- results = p .query (properties = properties )
125- assert len (results ['features' ]) == 1
126-
127- results = p .query (datetime_ = '2006-05-12' )
128- assert len (results ['features' ]) == 1
129-
130- results = p .query (datetime_ = '2004/2007' )
131- assert len (results ['features' ]) == 3
264+ assert len (results ['features' ]) == 2
132265
133266
134- def test_get (config ):
267+ def test_get (config , mock_csw ):
135268 p = CSWFacadeProvider (config )
136269
137270 result = p .get ('urn:uuid:a06af396-3105-442d-8b40-22b57a90d2f2' )
@@ -146,7 +279,7 @@ def test_get(config):
146279 assert 'service=CSW' in xml_link ['href' ]
147280
148281
149- def test_get_not_existing_item_raise_exception (config ):
282+ def test_get_not_existing_item_raise_exception (config , mock_csw ):
150283 """Testing query for a not existing object"""
151284 p = CSWFacadeProvider (config )
152285 with pytest .raises (ProviderItemNotFoundError ):
0 commit comments