88from uuid import uuid4
99
1010import httpx
11+ import pytest
1112import respx
13+ from faker import Faker
1214from httpx import AsyncClient
1315from models_library .api_schemas_webserver .functions import (
1416 FunctionJobCollection ,
2628from models_library .rest_pagination import PageMetaInfoLimitOffset
2729from models_library .users import UserID
2830from pytest_mock import MockType
31+ from pytest_simcore .helpers .httpx_calls_capture_models import HttpApiCallCaptureModel
2932from servicelib .aiohttp import status
33+ from servicelib .common_headers import (
34+ X_SIMCORE_PARENT_NODE_ID ,
35+ X_SIMCORE_PARENT_PROJECT_UUID ,
36+ )
3037from simcore_service_api_server ._meta import API_VTAG
3138
39+ _faker = Faker ()
40+
3241
3342async def test_register_function (
3443 client : AsyncClient ,
@@ -618,6 +627,15 @@ async def test_run_function_not_allowed(
618627 )
619628
620629
630+ @pytest .mark .parametrize (
631+ "parent_project_uuid, parent_node_uuid, expected_status_code" ,
632+ [
633+ (None , None , status .HTTP_422_UNPROCESSABLE_ENTITY ),
634+ (f"{ _faker .uuid4 ()} " , None , status .HTTP_422_UNPROCESSABLE_ENTITY ),
635+ (None , f"{ _faker .uuid4 ()} " , status .HTTP_422_UNPROCESSABLE_ENTITY ),
636+ (f"{ _faker .uuid4 ()} " , f"{ _faker .uuid4 ()} " , status .HTTP_200_OK ),
637+ ],
638+ )
621639async def test_run_function_parent_info (
622640 client : AsyncClient ,
623641 mock_handler_in_functions_rpc_interface : Callable [[str , Any ], None ],
@@ -630,13 +648,33 @@ async def test_run_function_parent_info(
630648 mocked_webserver_rpc_api : dict [str , MockType ],
631649 create_respx_mock_from_capture ,
632650 project_tests_dir : Path ,
651+ parent_project_uuid : str | None ,
652+ parent_node_uuid : str | None ,
653+ expected_status_code : int ,
633654) -> None :
634655
635656 capture = "run_function_parent_info.json"
657+
658+ def _default_side_effect (
659+ request : httpx .Request ,
660+ path_params : dict [str , Any ],
661+ capture : HttpApiCallCaptureModel ,
662+ ) -> Any :
663+ if request .method == "POST" and request .url .path .endswith ("/projects" ):
664+ if parent_project_uuid :
665+ _parent_uuid = request .headers .get (X_SIMCORE_PARENT_PROJECT_UUID )
666+ assert _parent_uuid is not None
667+ assert parent_project_uuid == _parent_uuid
668+ if parent_node_uuid :
669+ _parent_node_uuid = request .headers .get (X_SIMCORE_PARENT_NODE_ID )
670+ assert _parent_node_uuid is not None
671+ assert parent_node_uuid == _parent_node_uuid
672+ return capture .response_body
673+
636674 create_respx_mock_from_capture (
637675 respx_mocks = [mocked_webserver_rest_api_base , mocked_directorv2_rest_api_base ],
638676 capture_path = project_tests_dir / "mocks" / capture ,
639- side_effects_callbacks = [] ,
677+ side_effects_callbacks = [_default_side_effect ] * 50 ,
640678 )
641679
642680 mock_handler_in_functions_rpc_interface (
@@ -654,9 +692,15 @@ async def test_run_function_parent_info(
654692 "register_function_job" , mock_registered_function_job
655693 )
656694
695+ headers = dict ()
696+ if parent_project_uuid :
697+ headers [X_SIMCORE_PARENT_PROJECT_UUID ] = parent_project_uuid
698+ if parent_node_uuid :
699+ headers [X_SIMCORE_PARENT_NODE_ID ] = parent_node_uuid
657700 response = await client .post (
658701 f"{ API_VTAG } /functions/{ mock_registered_function .uid } :run" ,
659702 json = {},
660703 auth = auth ,
704+ headers = headers ,
661705 )
662- assert response .status_code == status . HTTP_200_OK
706+ assert response .status_code == expected_status_code
0 commit comments