@@ -722,3 +722,78 @@ async def test_get_async_job_links(
722722 assert response .status == return_status
723723 if return_schema :
724724 Envelope [return_schema ].model_validate (await response .json ())
725+
726+
727+ @pytest .fixture
728+ def create_consume_events_mock (
729+ mocker : MockerFixture ,
730+ ) -> Callable [[Any ], None ]:
731+ def _ (result_or_exception : Any ):
732+ async def mock_consume_events (* args , ** kwargs ):
733+ if isinstance (result_or_exception , Exception ):
734+ raise result_or_exception
735+ # Yield the mock events
736+ for event_id , event_data in result_or_exception :
737+ yield event_id , event_data
738+
739+ mock_task_manager = mocker .MagicMock ()
740+ mock_task_manager .consume_task_events = mock_consume_events
741+ mocker .patch (
742+ "simcore_service_webserver.tasks._controller._rest.get_task_manager" ,
743+ return_value = mock_task_manager ,
744+ )
745+
746+ return _
747+
748+
749+ class MockEvent :
750+ def __init__ (self , event_type : str , event_data : dict [str , Any ]):
751+ self .type = event_type
752+ self .data = event_data
753+
754+
755+ @pytest .mark .parametrize ("user_role" , _user_roles )
756+ @pytest .mark .parametrize (
757+ "backend_result_or_exception, expected_status" ,
758+ [
759+ (
760+ [
761+ ("event-1" , MockEvent ("status" , {"status" : "running" })),
762+ ("event-2" , MockEvent ("progress" , {"percent" : 50 })),
763+ ("event-3" , MockEvent ("status" , {"status" : "completed" })),
764+ ],
765+ status .HTTP_200_OK ,
766+ ),
767+ ([], status .HTTP_200_OK ), # No events
768+ ],
769+ ids = lambda x : (
770+ "with_events" if x and isinstance (x , list ) and len (x ) > 0 else "no_events"
771+ ),
772+ )
773+ async def test_get_async_job_stream (
774+ user_role : UserRole ,
775+ logged_user : UserInfoDict ,
776+ client : TestClient ,
777+ create_consume_events_mock : Callable [[Any ], None ],
778+ faker : Faker ,
779+ backend_result_or_exception : Any ,
780+ expected_status : int ,
781+ ):
782+ create_consume_events_mock (backend_result_or_exception )
783+
784+ _task_id = AsyncJobId (faker .uuid4 ())
785+
786+ response = await client .get (
787+ f"/{ API_VERSION } /tasks/{ _task_id } /stream" ,
788+ headers = {"Accept" : "text/event-stream" },
789+ )
790+ assert response .status == expected_status
791+
792+ if response .status == status .HTTP_200_OK :
793+ assert response .headers .get ("Content-Type" ) == "text/event-stream"
794+
795+ content = await response .text ()
796+ if backend_result_or_exception :
797+ assert "data:" in content or len (backend_result_or_exception ) == 0
798+ else :
799+ assert content == ""
0 commit comments