@@ -386,7 +386,6 @@ def test_publish_dataset_updates_project_collection_when_exists(
386386 self .assertIn (mock_gen .update_deepesdl_collection , update_methods )
387387
388388 def test_publish_dataset_raises_when_stac_root_missing (self ):
389- # stac_catalog_s3_root is mandatory; publish_dataset must raise ValueError
390389 self .publisher .dataset_config = {
391390 "collection_id" : "test-collection" ,
392391 "dataset_id" : "test-dataset" ,
@@ -395,6 +394,166 @@ def test_publish_dataset_raises_when_stac_root_missing(self):
395394 with pytest .raises (ValueError , match = "stac_catalog_s3_root" ):
396395 self .publisher .publish_dataset (write_to_file = False )
397396
397+ def test_publish_dataset_raises_when_no_dataset_config (self ):
398+ self .publisher .dataset_config = None
399+ with pytest .raises (ValueError , match = "No dataset config" ):
400+ self .publisher .publish_dataset (write_to_file = False )
401+
402+ def test_publish_dataset_raises_when_ids_missing (self ):
403+ self .publisher .dataset_config = {"collection_id" : "" , "dataset_id" : "" }
404+ with pytest .raises (ValueError , match = "Dataset ID or Collection ID missing" ):
405+ self .publisher .publish_dataset (write_to_file = False )
406+
407+ def test_publish_dataset_raises_when_license_missing (self ):
408+ self .publisher .dataset_config = {
409+ "collection_id" : "test-collection" ,
410+ "dataset_id" : "test-dataset" ,
411+ }
412+ with pytest .raises (ValueError , match = "license_type is required" ):
413+ self .publisher .publish_dataset (write_to_file = False )
414+
415+ def test_write_to_file_serializes_dict (self ):
416+ import json
417+ import os
418+ import tempfile
419+
420+ with tempfile .NamedTemporaryFile (delete = False , suffix = ".json" ) as f :
421+ path = f .name
422+ try :
423+ Publisher ._write_to_file (path , {"a" : 1 })
424+ with open (path ) as f :
425+ result = json .load (f )
426+ self .assertEqual (result , {"a" : 1 })
427+ finally :
428+ os .unlink (path )
429+
430+ def test_update_and_add_to_file_dict (self ):
431+ file_dict = {}
432+ self .publisher .gh_publisher .github_automation .local_clone_dir = "/tmp"
433+ update_method = MagicMock (return_value = {"key" : "value" })
434+ self .publisher ._update_and_add_to_file_dict (file_dict , "some/catalog.json" , update_method )
435+ update_method .assert_called_once ()
436+ assert any ("some/catalog.json" in str (k ) for k in file_dict )
437+
438+ def test_update_variable_catalogs_creates_new_when_missing (self ):
439+ mock_gen = MagicMock ()
440+ mock_gen .variables_metadata = {"var1" : {"variable_id" : "var1" }}
441+ mock_gen .build_variable_catalog .return_value .to_dict .return_value = {"id" : "var1" }
442+ self .publisher .gh_publisher .github_automation .file_exists .return_value = False
443+
444+ file_dict = {}
445+ self .publisher ._update_variable_catalogs (mock_gen , file_dict , ["var1" ])
446+
447+ mock_gen .build_variable_catalog .assert_called_once ()
448+ assert "variables/var1/catalog.json" in file_dict
449+
450+ def test_update_variable_catalogs_updates_existing (self ):
451+ mock_gen = MagicMock ()
452+ self .publisher .gh_publisher .github_automation .file_exists .return_value = True
453+ self .publisher .gh_publisher .github_automation .local_clone_dir = "/tmp"
454+ mock_gen .update_existing_variable_catalog .return_value = {"id" : "var1" }
455+
456+ file_dict = {}
457+ self .publisher ._update_variable_catalogs (mock_gen , file_dict , ["var1" ])
458+
459+ mock_gen .update_existing_variable_catalog .assert_called_once ()
460+ assert "variables/var1/catalog.json" in file_dict
461+
462+ # ------------------------------------------------------------------
463+ # generate_workflow_experiment_records
464+ # ------------------------------------------------------------------
465+
466+ def _setup_workflow_mocks (self ):
467+ """Patch all internals of generate_workflow_experiment_records."""
468+ mock_rg = MagicMock ()
469+ mock_props = MagicMock ()
470+ mock_props .jupyter_kernel_info .to_dict .return_value = {}
471+ mock_rg .build_record_properties .return_value = mock_props
472+
473+ mock_wf_record = MagicMock ()
474+ mock_wf_record .to_dict .return_value = {"id" : "wf" , "properties" : {}}
475+
476+ mock_exp_record = MagicMock ()
477+ mock_exp_record .to_dict .return_value = {
478+ "id" : "wf" ,
479+ "properties" : {},
480+ "jupyter_notebook_url" : "url" ,
481+ "collection_id" : "col" ,
482+ }
483+ return mock_rg , mock_props , mock_wf_record , mock_exp_record
484+
485+ @patch ("deep_code.tools.publish.WorkflowAsOgcRecord" )
486+ @patch ("deep_code.tools.publish.LinksBuilder" )
487+ @patch ("deep_code.tools.publish.OSCWorkflowOGCApiRecordGenerator" )
488+ def test_generate_workflow_records_mode_workflow (self , MockRG , MockLinks , MockWF ):
489+ mock_rg , mock_props , mock_wf_record , _ = self ._setup_workflow_mocks ()
490+ MockRG .return_value = mock_rg
491+ MockWF .return_value = mock_wf_record
492+
493+ self .publisher .workflow_config = {
494+ "workflow_id" : "my-workflow" ,
495+ "properties" : {"title" : "My WF" , "license" : "CC-BY-4.0" },
496+ }
497+ with patch .object (self .publisher , "_update_base_catalog" , return_value = {}):
498+ result = self .publisher .generate_workflow_experiment_records (
499+ write_to_file = False , mode = "workflow"
500+ )
501+
502+ self .assertIn ("workflows/my-workflow/record.json" , result )
503+ self .assertIn ("workflows/catalog.json" , result )
504+ self .assertNotIn ("experiments/catalog.json" , result )
505+
506+ @patch ("deep_code.tools.publish.ExperimentAsOgcRecord" )
507+ @patch ("deep_code.tools.publish.WorkflowAsOgcRecord" )
508+ @patch ("deep_code.tools.publish.LinksBuilder" )
509+ @patch ("deep_code.tools.publish.OSCWorkflowOGCApiRecordGenerator" )
510+ def test_generate_workflow_records_mode_all (self , MockRG , MockLinks , MockWF , MockExp ):
511+ mock_rg , mock_props , mock_wf_record , mock_exp_record = self ._setup_workflow_mocks ()
512+ MockRG .return_value = mock_rg
513+ MockWF .return_value = mock_wf_record
514+ MockExp .return_value = mock_exp_record
515+
516+ self .publisher .workflow_config = {
517+ "workflow_id" : "my-workflow" ,
518+ "properties" : {"title" : "My WF" , "license" : "CC-BY-4.0" },
519+ }
520+ self .publisher .collection_id = "my-collection"
521+ with patch .object (self .publisher , "_update_base_catalog" , return_value = {}):
522+ result = self .publisher .generate_workflow_experiment_records (
523+ write_to_file = False , mode = "all"
524+ )
525+
526+ self .assertIn ("workflows/my-workflow/record.json" , result )
527+ self .assertIn ("workflows/catalog.json" , result )
528+ self .assertIn ("experiments/catalog.json" , result )
529+
530+ @patch ("deep_code.tools.publish.OSCWorkflowOGCApiRecordGenerator" )
531+ def test_generate_workflow_records_raises_when_workflow_id_missing (self , MockRG ):
532+ self .publisher .workflow_config = {
533+ "properties" : {"title" : "My WF" , "license" : "CC-BY-4.0" },
534+ }
535+ with pytest .raises (ValueError , match = "workflow_id is missing" ):
536+ self .publisher .generate_workflow_experiment_records (
537+ write_to_file = False , mode = "workflow"
538+ )
539+
540+ @patch ("deep_code.tools.publish.OSCWorkflowOGCApiRecordGenerator" )
541+ def test_generate_workflow_records_raises_when_license_missing (self , MockRG ):
542+ self .publisher .workflow_config = {
543+ "workflow_id" : "my-wf" ,
544+ "properties" : {"title" : "My WF" },
545+ }
546+ with pytest .raises (ValueError , match = "license is required" ):
547+ self .publisher .generate_workflow_experiment_records (
548+ write_to_file = False , mode = "workflow"
549+ )
550+
551+ def test_generate_workflow_records_returns_empty_for_dataset_mode (self ):
552+ result = self .publisher .generate_workflow_experiment_records (
553+ write_to_file = False , mode = "dataset"
554+ )
555+ self .assertEqual (result , {})
556+
398557
399558class TestParseGithubNotebookUrl :
400559 @pytest .mark .parametrize (
0 commit comments