11package io .a2a .client ;
22
3-
43import java .util .Collections ;
54import java .util .List ;
65
@@ -24,26 +23,71 @@ public class ClientBuilderTest {
2423
2524 private AgentCard card = AgentCard .builder ()
2625 .name ("Hello World Agent" )
27- .description ("Just a hello world agent" )
28- .version ("1.0.0" )
29- .documentationUrl ("http://example.com/docs" )
30- .capabilities (AgentCapabilities .builder ()
31- .streaming (true )
32- .pushNotifications (true )
33- .build ())
26+ .description ("Just a hello world agent" )
27+ .version ("1.0.0" )
28+ .documentationUrl ("http://example.com/docs" )
29+ .capabilities (AgentCapabilities .builder ()
30+ .streaming (true )
31+ .pushNotifications (true )
32+ .build ())
3433 .defaultInputModes (Collections .singletonList ("text" ))
3534 .defaultOutputModes (Collections .singletonList ("text" ))
3635 .skills (Collections .singletonList (AgentSkill .builder ()
37- .id ("hello_world" )
38- .name ("Returns hello world" )
39- .description ("just returns hello world" )
40- .tags (Collections .singletonList ("hello world" ))
41- .examples (List .of ("hi" , "hello world" ))
42- .build ()))
36+ .id ("hello_world" )
37+ .name ("Returns hello world" )
38+ .description ("just returns hello world" )
39+ .tags (Collections .singletonList ("hello world" ))
40+ .examples (List .of ("hi" , "hello world" ))
41+ .build ()))
4342 .supportedInterfaces (List .of (
4443 new AgentInterface (TransportProtocol .JSONRPC .asString (), "http://localhost:9999" )))
4544 .build ();
4645
46+ private AgentCard cardWithTenant = AgentCard .builder ()
47+ .name ("Hello World Agent" )
48+ .description ("Just a hello world agent" )
49+ .version ("1.0.0" )
50+ .documentationUrl ("http://example.com/docs" )
51+ .capabilities (AgentCapabilities .builder ()
52+ .streaming (true )
53+ .pushNotifications (true )
54+ .build ())
55+ .defaultInputModes (Collections .singletonList ("text" ))
56+ .defaultOutputModes (Collections .singletonList ("text" ))
57+ .skills (Collections .singletonList (AgentSkill .builder ()
58+ .id ("hello_world" )
59+ .name ("Returns hello world" )
60+ .description ("just returns hello world" )
61+ .tags (Collections .singletonList ("hello world" ))
62+ .examples (List .of ("hi" , "hello world" ))
63+ .build ()))
64+ .supportedInterfaces (List .of (
65+ new AgentInterface (TransportProtocol .JSONRPC .asString (), "http://localhost:9999" , "/default-tenant" )))
66+ .build ();
67+
68+ private AgentCard cardWithMultipleInterfaces = AgentCard .builder ()
69+ .name ("Multi-Interface Agent" )
70+ .description ("Agent with multiple interfaces" )
71+ .version ("1.0.0" )
72+ .documentationUrl ("http://example.com/docs" )
73+ .capabilities (AgentCapabilities .builder ()
74+ .streaming (true )
75+ .pushNotifications (true )
76+ .build ())
77+ .defaultInputModes (Collections .singletonList ("text" ))
78+ .defaultOutputModes (Collections .singletonList ("text" ))
79+ .skills (Collections .singletonList (AgentSkill .builder ()
80+ .id ("hello_world" )
81+ .name ("Returns hello world" )
82+ .description ("just returns hello world" )
83+ .tags (Collections .singletonList ("hello world" ))
84+ .examples (List .of ("hi" , "hello world" ))
85+ .build ()))
86+ .supportedInterfaces (List .of (
87+ new AgentInterface (TransportProtocol .GRPC .asString (), "http://localhost:9998" , "/grpc-tenant" , "1.0" ),
88+ new AgentInterface (TransportProtocol .JSONRPC .asString (), "http://localhost:9999" , "/jsonrpc-tenant" , "1.0" )))
89+ .build ();
90+
4791 @ Test
4892 public void shouldNotFindCompatibleTransport () throws A2AClientException {
4993 A2AClientException exception = Assertions .assertThrows (A2AClientException .class ,
@@ -91,4 +135,75 @@ public void shouldCreateClient_differentConfigurations() throws A2AClientExcepti
91135
92136 Assertions .assertNotNull (client );
93137 }
138+
139+ @ Test
140+ public void shouldPreserveTenantFromAgentInterface () throws A2AClientException {
141+ ClientBuilder builder = Client
142+ .builder (cardWithTenant )
143+ .withTransport (JSONRPCTransport .class , new JSONRPCTransportConfigBuilder ());
144+
145+ AgentInterface selectedInterface = builder .findBestClientTransport ();
146+
147+ Assertions .assertEquals ("/default-tenant" , selectedInterface .tenant ());
148+ Assertions .assertEquals ("http://localhost:9999" , selectedInterface .url ());
149+ Assertions .assertEquals (TransportProtocol .JSONRPC .asString (), selectedInterface .protocolBinding ());
150+ }
151+
152+ @ Test
153+ public void shouldPreserveProtocolVersionFromAgentInterface () throws A2AClientException {
154+ ClientBuilder builder = Client
155+ .builder (cardWithMultipleInterfaces )
156+ .withTransport (JSONRPCTransport .class , new JSONRPCTransportConfigBuilder ());
157+
158+ AgentInterface selectedInterface = builder .findBestClientTransport ();
159+
160+ Assertions .assertEquals ("/jsonrpc-tenant" , selectedInterface .tenant ());
161+ Assertions .assertEquals ("1.0" , selectedInterface .protocolVersion ());
162+ }
163+
164+ @ Test
165+ public void shouldSelectCorrectInterfaceWithServerPreference () throws A2AClientException {
166+ // Server preference (default): iterates server interfaces in order, picks first that client supports
167+ // cardWithMultipleInterfaces has [GRPC, JSONRPC] - GRPC is first
168+ // Client supports both GRPC and JSONRPC, so GRPC should be selected (server's first choice)
169+ ClientBuilder builder = Client
170+ .builder (cardWithMultipleInterfaces )
171+ .withTransport (GrpcTransport .class , new GrpcTransportConfigBuilder ().channelFactory (s -> null ))
172+ .withTransport (JSONRPCTransport .class , new JSONRPCTransportConfigBuilder ());
173+
174+ AgentInterface selectedInterface = builder .findBestClientTransport ();
175+
176+ Assertions .assertEquals (TransportProtocol .GRPC .asString (), selectedInterface .protocolBinding ());
177+ Assertions .assertEquals ("http://localhost:9998" , selectedInterface .url ());
178+ Assertions .assertEquals ("/grpc-tenant" , selectedInterface .tenant ());
179+ }
180+
181+ @ Test
182+ public void shouldSelectCorrectInterfaceWithClientPreference () throws A2AClientException {
183+ // Client preference: iterates client transports in registration order, picks first that server supports
184+ // Client registers [JSONRPC, GRPC] - JSONRPC is first
185+ // Server supports both, so JSONRPC should be selected (client's first choice)
186+ ClientBuilder builder = Client
187+ .builder (cardWithMultipleInterfaces )
188+ .clientConfig (new ClientConfig .Builder ().setUseClientPreference (true ).build ())
189+ .withTransport (JSONRPCTransport .class , new JSONRPCTransportConfigBuilder ())
190+ .withTransport (GrpcTransport .class , new GrpcTransportConfigBuilder ().channelFactory (s -> null ));
191+
192+ AgentInterface selectedInterface = builder .findBestClientTransport ();
193+
194+ Assertions .assertEquals (TransportProtocol .JSONRPC .asString (), selectedInterface .protocolBinding ());
195+ Assertions .assertEquals ("http://localhost:9999" , selectedInterface .url ());
196+ Assertions .assertEquals ("/jsonrpc-tenant" , selectedInterface .tenant ());
197+ }
198+
199+ @ Test
200+ public void shouldPreserveEmptyTenant () throws A2AClientException {
201+ ClientBuilder builder = Client
202+ .builder (card )
203+ .withTransport (JSONRPCTransport .class , new JSONRPCTransportConfigBuilder ());
204+
205+ AgentInterface selectedInterface = builder .findBestClientTransport ();
206+
207+ Assertions .assertEquals ("" , selectedInterface .tenant ());
208+ }
94209}
0 commit comments