@@ -523,4 +523,265 @@ public function test_get_response_result_skips_null_messages(): void
523523
524524 $ this ->assertEquals ($ decodedMessages , $ result );
525525 }
526+
527+ /**
528+ * Test that handleResponseProcess executes matching handler successfully
529+ */
530+ public function test_handle_response_process_with_matching_handler (): void
531+ {
532+ $ clientId = 'response_client ' ;
533+ $ messageId = 'resp_123 ' ;
534+ $ result = ['data ' => 'response ' ];
535+ $ responseMessage = [
536+ 'jsonrpc ' => '2.0 ' ,
537+ 'id ' => $ messageId ,
538+ 'result ' => $ result ,
539+ ];
540+
541+ $ mockHandler = $ this ->createMock (\KLP \KlpMcpServer \Protocol \Handlers \ResponseHandler::class);
542+ $ mockHandler ->expects ($ this ->once ())
543+ ->method ('isHandle ' )
544+ ->with ($ messageId )
545+ ->willReturn (true );
546+
547+ $ mockHandler ->expects ($ this ->once ())
548+ ->method ('execute ' )
549+ ->with ($ clientId , $ messageId , $ result , null );
550+
551+ $ this ->mcpProtocol ->registerResponseHandler ($ mockHandler );
552+
553+ $ this ->mockTransport
554+ ->expects ($ this ->never ())
555+ ->method ('pushMessage ' );
556+
557+ $ this ->mcpProtocol ->handleMessage ($ clientId , $ responseMessage );
558+ }
559+
560+ /**
561+ * Test that handleResponseProcess silently ignores when no handler matches
562+ */
563+ public function test_handle_response_process_with_no_matching_handler (): void
564+ {
565+ $ clientId = 'response_client ' ;
566+ $ messageId = 'resp_456 ' ;
567+ $ responseMessage = [
568+ 'jsonrpc ' => '2.0 ' ,
569+ 'id ' => $ messageId ,
570+ 'result ' => ['data ' => 'test ' ],
571+ ];
572+
573+ $ mockHandler = $ this ->createMock (\KLP \KlpMcpServer \Protocol \Handlers \ResponseHandler::class);
574+ $ mockHandler ->expects ($ this ->once ())
575+ ->method ('isHandle ' )
576+ ->with ($ messageId )
577+ ->willReturn (false );
578+
579+ $ mockHandler ->expects ($ this ->never ())
580+ ->method ('execute ' );
581+
582+ $ this ->mcpProtocol ->registerResponseHandler ($ mockHandler );
583+
584+ $ this ->mockTransport
585+ ->expects ($ this ->never ())
586+ ->method ('pushMessage ' );
587+
588+ $ this ->mcpProtocol ->handleMessage ($ clientId , $ responseMessage );
589+ }
590+
591+ /**
592+ * Test that handleResponseProcess pushes error when handler throws JsonRpcErrorException
593+ */
594+ public function test_handle_response_process_handler_throws_json_rpc_error (): void
595+ {
596+ $ clientId = 'response_client ' ;
597+ $ messageId = 'resp_789 ' ;
598+ $ responseMessage = [
599+ 'jsonrpc ' => '2.0 ' ,
600+ 'id ' => $ messageId ,
601+ 'result ' => ['data ' => 'test ' ],
602+ ];
603+
604+ $ mockHandler = $ this ->createMock (\KLP \KlpMcpServer \Protocol \Handlers \ResponseHandler::class);
605+ $ mockHandler ->expects ($ this ->once ())
606+ ->method ('isHandle ' )
607+ ->with ($ messageId )
608+ ->willReturn (true );
609+
610+ $ expectedException = new \KLP \KlpMcpServer \Exceptions \JsonRpcErrorException (
611+ 'Handler error ' ,
612+ \KLP \KlpMcpServer \Exceptions \Enums \JsonRpcErrorCode::INTERNAL_ERROR
613+ );
614+
615+ $ mockHandler ->expects ($ this ->once ())
616+ ->method ('execute ' )
617+ ->with ($ clientId , $ messageId , ['data ' => 'test ' ], null )
618+ ->willThrowException ($ expectedException );
619+
620+ $ this ->mcpProtocol ->registerResponseHandler ($ mockHandler );
621+
622+ $ this ->mockTransport
623+ ->expects ($ this ->once ())
624+ ->method ('pushMessage ' )
625+ ->with ($ this ->callback (function (...$ args ) use ($ clientId , $ messageId ) {
626+ $ data = $ args [1 ];
627+ $ this ->assertEquals ($ clientId , $ args [0 ]);
628+ $ this ->assertEquals ('2.0 ' , $ data ['jsonrpc ' ]);
629+ $ this ->assertEquals ($ messageId , $ data ['id ' ]);
630+ $ this ->assertEquals (-32603 , $ data ['error ' ]['code ' ]);
631+ $ this ->assertEquals ('Handler error ' , $ data ['error ' ]['message ' ]);
632+
633+ return true ;
634+ }));
635+
636+ $ this ->mcpProtocol ->handleMessage ($ clientId , $ responseMessage );
637+ }
638+
639+ /**
640+ * Test that handleResponseProcess wraps generic Exception as INTERNAL_ERROR
641+ */
642+ public function test_handle_response_process_handler_throws_generic_exception (): void
643+ {
644+ $ clientId = 'response_client ' ;
645+ $ messageId = 'resp_101 ' ;
646+ $ responseMessage = [
647+ 'jsonrpc ' => '2.0 ' ,
648+ 'id ' => $ messageId ,
649+ 'result ' => ['data ' => 'test ' ],
650+ ];
651+
652+ $ mockHandler = $ this ->createMock (\KLP \KlpMcpServer \Protocol \Handlers \ResponseHandler::class);
653+ $ mockHandler ->expects ($ this ->once ())
654+ ->method ('isHandle ' )
655+ ->with ($ messageId )
656+ ->willReturn (true );
657+
658+ $ mockHandler ->expects ($ this ->once ())
659+ ->method ('execute ' )
660+ ->with ($ clientId , $ messageId , ['data ' => 'test ' ], null )
661+ ->willThrowException (new \RuntimeException ('Unexpected error ' ));
662+
663+ $ this ->mcpProtocol ->registerResponseHandler ($ mockHandler );
664+
665+ $ this ->mockTransport
666+ ->expects ($ this ->once ())
667+ ->method ('pushMessage ' )
668+ ->with ($ this ->callback (function (...$ args ) use ($ clientId , $ messageId ) {
669+ $ data = $ args [1 ];
670+ $ this ->assertEquals ($ clientId , $ args [0 ]);
671+ $ this ->assertEquals ('2.0 ' , $ data ['jsonrpc ' ]);
672+ $ this ->assertEquals ($ messageId , $ data ['id ' ]);
673+ $ this ->assertEquals (-32603 , $ data ['error ' ]['code ' ]);
674+ $ this ->assertEquals ('Unexpected error ' , $ data ['error ' ]['message ' ]);
675+
676+ return true ;
677+ }));
678+
679+ $ this ->mcpProtocol ->handleMessage ($ clientId , $ responseMessage );
680+ }
681+
682+ /**
683+ * Test that handleResponseProcess returns early on first matching handler
684+ */
685+ public function test_handle_response_process_early_return_first_match (): void
686+ {
687+ $ clientId = 'response_client ' ;
688+ $ messageId = 'resp_202 ' ;
689+ $ responseMessage = [
690+ 'jsonrpc ' => '2.0 ' ,
691+ 'id ' => $ messageId ,
692+ 'result ' => ['data ' => 'test ' ],
693+ ];
694+
695+ $ firstHandler = $ this ->createMock (\KLP \KlpMcpServer \Protocol \Handlers \ResponseHandler::class);
696+ $ firstHandler ->expects ($ this ->once ())
697+ ->method ('isHandle ' )
698+ ->with ($ messageId )
699+ ->willReturn (true );
700+
701+ $ firstHandler ->expects ($ this ->once ())
702+ ->method ('execute ' )
703+ ->with ($ clientId , $ messageId , ['data ' => 'test ' ], null );
704+
705+ $ secondHandler = $ this ->createMock (\KLP \KlpMcpServer \Protocol \Handlers \ResponseHandler::class);
706+ $ secondHandler ->expects ($ this ->never ())
707+ ->method ('isHandle ' );
708+
709+ $ secondHandler ->expects ($ this ->never ())
710+ ->method ('execute ' );
711+
712+ $ this ->mcpProtocol ->registerResponseHandler ($ firstHandler );
713+ $ this ->mcpProtocol ->registerResponseHandler ($ secondHandler );
714+
715+ $ this ->mockTransport
716+ ->expects ($ this ->never ())
717+ ->method ('pushMessage ' );
718+
719+ $ this ->mcpProtocol ->handleMessage ($ clientId , $ responseMessage );
720+ }
721+
722+ /**
723+ * Test that handleResponseProcess passes result data correctly to handler
724+ */
725+ public function test_handle_response_process_with_result_data (): void
726+ {
727+ $ clientId = 'response_client ' ;
728+ $ messageId = 'resp_303 ' ;
729+ $ result = ['key1 ' => 'value1 ' , 'key2 ' => ['nested ' => 'data ' ]];
730+ $ responseMessage = [
731+ 'jsonrpc ' => '2.0 ' ,
732+ 'id ' => $ messageId ,
733+ 'result ' => $ result ,
734+ ];
735+
736+ $ mockHandler = $ this ->createMock (\KLP \KlpMcpServer \Protocol \Handlers \ResponseHandler::class);
737+ $ mockHandler ->expects ($ this ->once ())
738+ ->method ('isHandle ' )
739+ ->with ($ messageId )
740+ ->willReturn (true );
741+
742+ $ mockHandler ->expects ($ this ->once ())
743+ ->method ('execute ' )
744+ ->with ($ clientId , $ messageId , $ result , null );
745+
746+ $ this ->mcpProtocol ->registerResponseHandler ($ mockHandler );
747+
748+ $ this ->mockTransport
749+ ->expects ($ this ->never ())
750+ ->method ('pushMessage ' );
751+
752+ $ this ->mcpProtocol ->handleMessage ($ clientId , $ responseMessage );
753+ }
754+
755+ /**
756+ * Test that handleResponseProcess passes error data correctly to handler
757+ */
758+ public function test_handle_response_process_with_error_data (): void
759+ {
760+ $ clientId = 'response_client ' ;
761+ $ messageId = 'resp_404 ' ;
762+ $ error = ['code ' => -32600 , 'message ' => 'Invalid Request ' ];
763+ $ responseMessage = [
764+ 'jsonrpc ' => '2.0 ' ,
765+ 'id ' => $ messageId ,
766+ 'error ' => $ error ,
767+ ];
768+
769+ $ mockHandler = $ this ->createMock (\KLP \KlpMcpServer \Protocol \Handlers \ResponseHandler::class);
770+ $ mockHandler ->expects ($ this ->once ())
771+ ->method ('isHandle ' )
772+ ->with ($ messageId )
773+ ->willReturn (true );
774+
775+ $ mockHandler ->expects ($ this ->once ())
776+ ->method ('execute ' )
777+ ->with ($ clientId , $ messageId , null , $ error );
778+
779+ $ this ->mcpProtocol ->registerResponseHandler ($ mockHandler );
780+
781+ $ this ->mockTransport
782+ ->expects ($ this ->never ())
783+ ->method ('pushMessage ' );
784+
785+ $ this ->mcpProtocol ->handleMessage ($ clientId , $ responseMessage );
786+ }
526787}
0 commit comments