@@ -150,9 +150,9 @@ async def _patch_registered_function_job_side_effect(
150150 registered_function_job_patch = kwargs ["registered_function_job_patch" ]
151151 assert isinstance (registered_function_job_patch , RegisteredProjectFunctionJobPatch )
152152 job_creation_task_id = registered_function_job_patch .job_creation_task_id
153- assert job_creation_task_id is not None
153+ uid = kwargs [ "function_job_uuid" ]
154154 return mock_registered_project_function_job .model_copy (
155- update = {"job_creation_task_id" : job_creation_task_id }
155+ update = {"job_creation_task_id" : job_creation_task_id , "uid" : uid }
156156 )
157157
158158
@@ -551,3 +551,130 @@ def _default_side_effect(
551551 ].job_creation_task_id
552552 await wait_for_task_result (client , auth , f"{ task_id } " )
553553 assert side_effect_checks ["headers_checked" ] is True
554+
555+
556+ @pytest .mark .parametrize ("capture" , ["run_study_function_parent_info.json" ])
557+ @pytest .mark .parametrize ("mocked_app_dependencies" , [None ])
558+ async def test_map_function (
559+ app : FastAPI ,
560+ with_api_server_celery_worker : TestWorkController ,
561+ client : AsyncClient ,
562+ mock_handler_in_functions_rpc_interface : Callable [
563+ [str , Any , Exception | None , Callable | None ], MockType
564+ ],
565+ mock_registered_project_function : RegisteredProjectFunction ,
566+ mock_registered_project_function_job : RegisteredFunctionJob ,
567+ auth : httpx .BasicAuth ,
568+ user_id : UserID ,
569+ mocked_webserver_rest_api_base : respx .MockRouter ,
570+ mocked_directorv2_rest_api_base : respx .MockRouter ,
571+ mocked_webserver_rpc_api : dict [str , MockType ],
572+ create_respx_mock_from_capture ,
573+ project_tests_dir : Path ,
574+ capture : str ,
575+ ) -> None :
576+
577+ def _default_side_effect (
578+ request : httpx .Request ,
579+ path_params : dict [str , Any ],
580+ capture : HttpApiCallCaptureModel ,
581+ ) -> Any :
582+ return capture .response_body
583+
584+ create_respx_mock_from_capture (
585+ respx_mocks = [mocked_webserver_rest_api_base , mocked_directorv2_rest_api_base ],
586+ capture_path = project_tests_dir / "mocks" / capture ,
587+ side_effects_callbacks = [_default_side_effect ] * 50 ,
588+ )
589+
590+ mock_handler_in_functions_rpc_interface (
591+ "get_function_user_permissions" ,
592+ FunctionUserAccessRights (
593+ user_id = user_id ,
594+ execute = True ,
595+ read = True ,
596+ write = True ,
597+ ),
598+ None ,
599+ None ,
600+ )
601+ mock_handler_in_functions_rpc_interface (
602+ "get_function" , mock_registered_project_function , None , None
603+ )
604+ mock_handler_in_functions_rpc_interface ("find_cached_function_jobs" , [], None , None )
605+
606+ _generated_function_job_ids : list [FunctionJobID ] = []
607+
608+ async def _register_function_job_side_effect (
609+ generated_function_job_ids : list [FunctionJobID ], * args , ** kwargs
610+ ):
611+ uid = FunctionJobID (_faker .uuid4 ())
612+ generated_function_job_ids .append (uid )
613+ return mock_registered_project_function_job .model_copy (update = {"uid" : uid })
614+
615+ mock_handler_in_functions_rpc_interface (
616+ "register_function_job" ,
617+ None ,
618+ None ,
619+ partial (_register_function_job_side_effect , _generated_function_job_ids ),
620+ )
621+ mock_handler_in_functions_rpc_interface (
622+ "get_functions_user_api_access_rights" ,
623+ FunctionUserApiAccessRights (
624+ user_id = user_id ,
625+ execute_functions = True ,
626+ write_functions = True ,
627+ read_functions = True ,
628+ ),
629+ None ,
630+ None ,
631+ )
632+
633+ async def _register_function_job_collection_side_effect (* args , ** kwargs ):
634+ job_collection = kwargs ["function_job_collection" ]
635+ return RegisteredFunctionJobCollection (
636+ uid = FunctionJobID (_faker .uuid4 ()),
637+ title = "Test Collection" ,
638+ description = "A test function job collection" ,
639+ job_ids = job_collection .job_ids ,
640+ created_at = datetime .datetime .now (datetime .UTC ),
641+ )
642+
643+ mock_handler_in_functions_rpc_interface (
644+ "register_function_job_collection" ,
645+ None ,
646+ None ,
647+ _register_function_job_collection_side_effect ,
648+ )
649+
650+ patch_mock = mock_handler_in_functions_rpc_interface (
651+ "patch_registered_function_job" ,
652+ None ,
653+ None ,
654+ partial (
655+ _patch_registered_function_job_side_effect ,
656+ mock_registered_project_function_job ,
657+ ),
658+ )
659+
660+ _inputs = [{}, {}]
661+ response = await client .post (
662+ f"{ API_VTAG } /functions/{ mock_registered_project_function .uid } :map" ,
663+ json = _inputs ,
664+ auth = auth ,
665+ headers = {
666+ X_SIMCORE_PARENT_PROJECT_UUID : "null" ,
667+ X_SIMCORE_PARENT_NODE_ID : "null" ,
668+ },
669+ )
670+ assert response .status_code == status .HTTP_200_OK
671+
672+ job_collection = FunctionJobCollection .model_validate (response .json ())
673+ assert job_collection .job_ids == _generated_function_job_ids
674+ celery_task_ids = {
675+ elm .kwargs ["registered_function_job_patch" ].job_creation_task_id
676+ for elm in patch_mock .call_args_list
677+ }
678+ assert len (celery_task_ids ) == len (_inputs )
679+ for task_id in celery_task_ids :
680+ await wait_for_task_result (client , auth , f"{ task_id } " )
0 commit comments