1414import static io .a2a .client .JsonMessages .SEND_MESSAGE_TEST_RESPONSE ;
1515import static io .a2a .client .JsonMessages .SEND_MESSAGE_TEST_RESPONSE_WITH_MESSAGE_RESPONSE ;
1616import static io .a2a .client .JsonMessages .SEND_MESSAGE_WITH_ERROR_TEST_REQUEST ;
17+ import static io .a2a .client .JsonMessages .SEND_MESSAGE_WITH_FILE_PART_TEST_REQUEST ;
18+ import static io .a2a .client .JsonMessages .SEND_MESSAGE_WITH_FILE_PART_TEST_RESPONSE ;
19+ import static io .a2a .client .JsonMessages .SEND_MESSAGE_WITH_DATA_PART_TEST_REQUEST ;
20+ import static io .a2a .client .JsonMessages .SEND_MESSAGE_WITH_DATA_PART_TEST_RESPONSE ;
21+ import static io .a2a .client .JsonMessages .SEND_MESSAGE_WITH_MIXED_PARTS_TEST_REQUEST ;
22+ import static io .a2a .client .JsonMessages .SEND_MESSAGE_WITH_MIXED_PARTS_TEST_RESPONSE ;
1723import static io .a2a .client .JsonMessages .SET_TASK_PUSH_NOTIFICATION_CONFIG_TEST_REQUEST ;
1824import static io .a2a .client .JsonMessages .SET_TASK_PUSH_NOTIFICATION_CONFIG_TEST_RESPONSE ;
1925import static org .junit .jupiter .api .Assertions .assertEquals ;
3541import io .a2a .spec .AgentSkill ;
3642import io .a2a .spec .Artifact ;
3743import io .a2a .spec .CancelTaskResponse ;
44+ import io .a2a .spec .DataPart ;
3845import io .a2a .spec .FileContent ;
3946import io .a2a .spec .FilePart ;
4047import io .a2a .spec .FileWithBytes ;
@@ -508,4 +515,183 @@ public void testA2AClientGetAuthenticatedExtendedAgentCard() throws Exception {
508515 assertTrue (agentCard .supportsAuthenticatedExtendedCard ());
509516 assertEquals ("https://georoute-agent.example.com/icon.png" , agentCard .iconUrl ());
510517 }
518+
519+ @ Test
520+ public void testA2AClientSendMessageWithFilePart () throws Exception {
521+ this .server .when (
522+ request ()
523+ .withMethod ("POST" )
524+ .withPath ("/" )
525+ .withBody (JsonBody .json (SEND_MESSAGE_WITH_FILE_PART_TEST_REQUEST , MatchType .STRICT ))
526+
527+ )
528+ .respond (
529+ response ()
530+ .withStatusCode (200 )
531+ .withBody (SEND_MESSAGE_WITH_FILE_PART_TEST_RESPONSE )
532+ );
533+
534+ A2AClient client = new A2AClient ("http://localhost:4001" );
535+ Message message = new Message .Builder ()
536+ .role (Message .Role .USER )
537+ .parts (List .of (
538+ new TextPart ("analyze this image" ),
539+ new FilePart (new FileWithUri ("image/jpeg" , null , "file:///path/to/image.jpg" ))
540+ ))
541+ .contextId ("context-1234" )
542+ .messageId ("message-1234-with-file" )
543+ .build ();
544+ MessageSendConfiguration configuration = new MessageSendConfiguration .Builder ()
545+ .acceptedOutputModes (List .of ("text" ))
546+ .blocking (true )
547+ .build ();
548+ MessageSendParams params = new MessageSendParams .Builder ()
549+ .message (message )
550+ .configuration (configuration )
551+ .build ();
552+
553+ SendMessageResponse response = client .sendMessage ("request-1234-with-file" , params );
554+
555+ assertEquals ("2.0" , response .getJsonrpc ());
556+ assertNotNull (response .getId ());
557+ Object result = response .getResult ();
558+ assertInstanceOf (Task .class , result );
559+ Task task = (Task ) result ;
560+ assertEquals ("de38c76d-d54c-436c-8b9f-4c2703648d64" , task .getId ());
561+ assertNotNull (task .getContextId ());
562+ assertEquals (TaskState .COMPLETED , task .getStatus ().state ());
563+ assertEquals (1 , task .getArtifacts ().size ());
564+ Artifact artifact = task .getArtifacts ().get (0 );
565+ assertEquals ("artifact-1" , artifact .artifactId ());
566+ assertEquals ("image-analysis" , artifact .name ());
567+ assertEquals (1 , artifact .parts ().size ());
568+ Part <?> part = artifact .parts ().get (0 );
569+ assertEquals (Part .Kind .TEXT , part .getKind ());
570+ assertEquals ("This is an image of a cat sitting on a windowsill." , ((TextPart ) part ).getText ());
571+ assertTrue (task .getMetadata ().isEmpty ());
572+ }
573+
574+ @ Test
575+ public void testA2AClientSendMessageWithDataPart () throws Exception {
576+ this .server .when (
577+ request ()
578+ .withMethod ("POST" )
579+ .withPath ("/" )
580+ .withBody (JsonBody .json (SEND_MESSAGE_WITH_DATA_PART_TEST_REQUEST , MatchType .STRICT ))
581+
582+ )
583+ .respond (
584+ response ()
585+ .withStatusCode (200 )
586+ .withBody (SEND_MESSAGE_WITH_DATA_PART_TEST_RESPONSE )
587+ );
588+
589+ A2AClient client = new A2AClient ("http://localhost:4001" );
590+
591+ Map <String , Object > data = new HashMap <>();
592+ data .put ("temperature" , 25.5 );
593+ data .put ("humidity" , 60.2 );
594+ data .put ("location" , "San Francisco" );
595+ data .put ("timestamp" , "2024-01-15T10:30:00Z" );
596+
597+ Message message = new Message .Builder ()
598+ .role (Message .Role .USER )
599+ .parts (List .of (
600+ new TextPart ("process this data" ),
601+ new DataPart (data )
602+ ))
603+ .contextId ("context-1234" )
604+ .messageId ("message-1234-with-data" )
605+ .build ();
606+ MessageSendConfiguration configuration = new MessageSendConfiguration .Builder ()
607+ .acceptedOutputModes (List .of ("text" ))
608+ .blocking (true )
609+ .build ();
610+ MessageSendParams params = new MessageSendParams .Builder ()
611+ .message (message )
612+ .configuration (configuration )
613+ .build ();
614+
615+ SendMessageResponse response = client .sendMessage ("request-1234-with-data" , params );
616+
617+ assertEquals ("2.0" , response .getJsonrpc ());
618+ assertNotNull (response .getId ());
619+ Object result = response .getResult ();
620+ assertInstanceOf (Task .class , result );
621+ Task task = (Task ) result ;
622+ assertEquals ("de38c76d-d54c-436c-8b9f-4c2703648d64" , task .getId ());
623+ assertNotNull (task .getContextId ());
624+ assertEquals (TaskState .COMPLETED , task .getStatus ().state ());
625+ assertEquals (1 , task .getArtifacts ().size ());
626+ Artifact artifact = task .getArtifacts ().get (0 );
627+ assertEquals ("artifact-1" , artifact .artifactId ());
628+ assertEquals ("data-analysis" , artifact .name ());
629+ assertEquals (1 , artifact .parts ().size ());
630+ Part <?> part = artifact .parts ().get (0 );
631+ assertEquals (Part .Kind .TEXT , part .getKind ());
632+ assertEquals ("Processed weather data: Temperature is 25.5°C, humidity is 60.2% in San Francisco." , ((TextPart ) part ).getText ());
633+ assertTrue (task .getMetadata ().isEmpty ());
634+ }
635+
636+ @ Test
637+ public void testA2AClientSendMessageWithMixedParts () throws Exception {
638+ this .server .when (
639+ request ()
640+ .withMethod ("POST" )
641+ .withPath ("/" )
642+ .withBody (JsonBody .json (SEND_MESSAGE_WITH_MIXED_PARTS_TEST_REQUEST , MatchType .STRICT ))
643+
644+ )
645+ .respond (
646+ response ()
647+ .withStatusCode (200 )
648+ .withBody (SEND_MESSAGE_WITH_MIXED_PARTS_TEST_RESPONSE )
649+ );
650+
651+ A2AClient client = new A2AClient ("http://localhost:4001" );
652+
653+ Map <String , Object > data = new HashMap <>();
654+ data .put ("chartType" , "bar" );
655+ data .put ("dataPoints" , List .of (10 , 20 , 30 , 40 ));
656+ data .put ("labels" , List .of ("Q1" , "Q2" , "Q3" , "Q4" ));
657+
658+ Message message = new Message .Builder ()
659+ .role (Message .Role .USER )
660+ .parts (List .of (
661+ new TextPart ("analyze this data and image" ),
662+ new FilePart (new FileWithBytes ("image/png" , "chart.png" , "aGVsbG8=" )),
663+ new DataPart (data )
664+ ))
665+ .contextId ("context-1234" )
666+ .messageId ("message-1234-with-mixed" )
667+ .build ();
668+ MessageSendConfiguration configuration = new MessageSendConfiguration .Builder ()
669+ .acceptedOutputModes (List .of ("text" ))
670+ .blocking (true )
671+ .build ();
672+ MessageSendParams params = new MessageSendParams .Builder ()
673+ .message (message )
674+ .configuration (configuration )
675+ .build ();
676+
677+ SendMessageResponse response = client .sendMessage ("request-1234-with-mixed" , params );
678+
679+ assertEquals ("2.0" , response .getJsonrpc ());
680+ assertNotNull (response .getId ());
681+ Object result = response .getResult ();
682+ assertInstanceOf (Task .class , result );
683+ Task task = (Task ) result ;
684+ assertEquals ("de38c76d-d54c-436c-8b9f-4c2703648d64" , task .getId ());
685+ assertNotNull (task .getContextId ());
686+ assertEquals (TaskState .COMPLETED , task .getStatus ().state ());
687+ assertEquals (1 , task .getArtifacts ().size ());
688+ Artifact artifact = task .getArtifacts ().get (0 );
689+ assertEquals ("artifact-1" , artifact .artifactId ());
690+ assertEquals ("mixed-analysis" , artifact .name ());
691+ assertEquals (1 , artifact .parts ().size ());
692+ Part <?> part = artifact .parts ().get (0 );
693+ assertEquals (Part .Kind .TEXT , part .getKind ());
694+ assertEquals ("Analyzed chart image and data: Bar chart showing quarterly data with values [10, 20, 30, 40]." , ((TextPart ) part ).getText ());
695+ assertTrue (task .getMetadata ().isEmpty ());
696+ }
511697}
0 commit comments