@@ -60,14 +60,15 @@ def _get_user_name():
60
60
61
61
@pytest .fixture
62
62
def configurable_harvester ():
63
- def _create (record_return_value ):
63
+ def _create (record_return_value , package_return_value ):
64
64
class DummyFDPHarvester (CivityHarvester ):
65
65
def setup_record_provider (self , url , config ):
66
66
self .record_provider = MagicMock ()
67
67
self .record_provider .get_record_by_id = MagicMock (return_value = record_return_value )
68
68
69
69
def setup_record_to_package_converter (self , url , config ):
70
- pass
70
+ self .record_to_package_converter = MagicMock ()
71
+ self .record_to_package_converter .record_to_package = MagicMock (return_value = package_return_value )
71
72
return DummyFDPHarvester ()
72
73
return _create
73
74
@@ -192,15 +193,15 @@ def test_fetch_stage_status_delete(dummy_harvester, harvest_object):
192
193
assert result is True
193
194
194
195
def test_fetch_stage_successful_fetch (configurable_harvester , harvest_object ):
195
- harvester = configurable_harvester ("<rdf>dummy content</rdf>" )
196
+ harvester = configurable_harvester ("<rdf>dummy content</rdf>" , configurable_harvester )
196
197
result = harvester .fetch_stage (harvest_object )
197
198
198
199
assert result is True
199
200
assert harvest_object .content == "<rdf>dummy content</rdf>"
200
201
harvest_object .save .assert_called_once ()
201
202
202
203
def test_fetch_stage_empty_record (configurable_harvester , harvest_object ):
203
- harvester = configurable_harvester (None )
204
+ harvester = configurable_harvester (None , None )
204
205
harvester ._save_object_error = MagicMock ()
205
206
harvest_object .extras = [HOExtra (key = "status" , value = "change" )]
206
207
@@ -251,19 +252,24 @@ def test_import_stage_conversion_error(dummy_harvester, harvest_object):
251
252
252
253
253
254
def test_import_stage_success_new_package (dummy_harvester , harvest_object ):
254
- dummy_harvester .setup_record_to_package_converter (harvest_object .source .url , {})
255
- dummy_harvester .record_to_package_converter .record_to_package .return_value = {
255
+ harvester = dummy_harvester
256
+ harvester .setup_record_to_package_converter (harvest_object .source .url , {})
257
+ harvester .record_to_package_converter .record_to_package .return_value = {
256
258
"title" : "My Dataset" ,
259
+ "name" : "my-dataset" ,
257
260
"resources" : []
258
261
}
262
+
259
263
harvest_object .content = "<rdf>dummy content</rdf>"
264
+ # Ensure _create_or_update_package and _create_resources are mocked for isolation
265
+ harvester ._create_or_update_package = MagicMock (return_value = "pkg-123" )
266
+ harvester ._create_resources = MagicMock (return_value = True )
260
267
261
268
with patch ("ckanext.fairdatapoint.harvesters.civity_harvester.model.Session" ) as mock_session :
262
- result = dummy_harvester .import_stage (harvest_object )
263
-
269
+ result = harvester .import_stage (harvest_object )
264
270
assert result is True
265
- dummy_harvester ._create_or_update_package .assert_called_once ()
266
- dummy_harvester ._create_resources .assert_called_once ()
271
+ harvester ._create_or_update_package .assert_called_once ()
272
+ harvester ._create_resources .assert_called_once ()
267
273
assert harvest_object .current is True
268
274
harvest_object .add .assert_called ()
269
275
mock_session .commit .assert_called ()
@@ -287,3 +293,44 @@ def test_import_stage_success_update(dummy_harvester, harvest_object):
287
293
dummy_harvester ._create_or_update_package .assert_called_once ()
288
294
dummy_harvester ._create_resources .assert_called_once ()
289
295
mock_session .commit .assert_called ()
296
+
297
+
298
+ def test_import_stage_dataset_links_to_existing_series (configurable_harvester , harvest_object ):
299
+ # This test verifies that a dataset can be updated to include a link to an existing dataseries.
300
+ # Note: The reverse (adding datasets to a dataseries) is not handled here.
301
+ dataset_guid = "dataset=https://fdp.example.org/dataset/abc"
302
+ dataseries_guid = "dataseries=https://fdp.example.org/datasetseries/xyz"
303
+ harvest_object .guid = dataset_guid
304
+ harvest_object .extras = [HOExtra (key = "status" , value = "change" )]
305
+ harvest_object .package_id = "existing-dataset"
306
+ harvest_object .content = "<rdf>dummy dataset referencing series</rdf>"
307
+
308
+ package_to_return = {
309
+ "title" : "Updated Dataset" ,
310
+ "name" : "updated-dataset" ,
311
+ "resources" : [],
312
+ "in_series" : [dataseries_guid ],
313
+ "owner_org" : harvest_object .owner_org ,
314
+ }
315
+
316
+ harvester = configurable_harvester (harvest_object .content , package_to_return )
317
+ harvester ._create_or_update_package = MagicMock (return_value = "pkg-123" )
318
+
319
+ with patch ("ckanext.fairdatapoint.harvesters.civity_harvester.model.Session" ) as mock_session , \
320
+ patch ("ckanext.fairdatapoint.harvesters.civity_harvester.toolkit.get_action" ) as mock_get_action :
321
+ mock_query = MagicMock ()
322
+ mock_query .join .return_value .filter .return_value .filter .return_value .filter .return_value .all .return_value = [
323
+ (dataseries_guid , "series-xyz" )
324
+ ]
325
+ mock_session .query .return_value = mock_query
326
+
327
+ result = harvester .import_stage (harvest_object )
328
+
329
+ assert result is True
330
+ assert harvest_object .current is True
331
+ harvester ._create_or_update_package .assert_called_once ()
332
+ updated_pkg = harvester ._create_or_update_package .call_args [0 ][0 ]
333
+ assert updated_pkg ["id" ] == "existing-dataset"
334
+ # Ensure that only the dataset receives the in_series update
335
+ assert dataseries_guid in updated_pkg ["in_series" ]
336
+ mock_session .commit .assert_called ()
0 commit comments