|
1 | 1 | package io.a2a.server.apps.quarkus; |
2 | 2 |
|
| 3 | +import static io.a2a.common.MediaType.APPLICATION_PROBLEM_JSON; |
| 4 | +import static io.a2a.spec.A2AMethods.DELETE_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; |
| 5 | +import static io.a2a.spec.A2AMethods.GET_TASK_METHOD; |
| 6 | +import static io.a2a.spec.A2AMethods.GET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; |
| 7 | +import static io.a2a.spec.A2AMethods.LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; |
| 8 | +import static io.a2a.spec.A2AMethods.SEND_MESSAGE_METHOD; |
| 9 | +import static io.a2a.spec.A2AMethods.SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; |
| 10 | +import static io.a2a.spec.A2AMethods.SUBSCRIBE_TO_TASK_METHOD; |
3 | 11 | import static io.a2a.spec.A2AMethods.CANCEL_TASK_METHOD; |
4 | 12 | import static io.a2a.spec.A2AMethods.GET_EXTENDED_AGENT_CARD_METHOD; |
5 | 13 | import static io.a2a.spec.A2AMethods.SEND_STREAMING_MESSAGE_METHOD; |
6 | 14 | import static io.a2a.transport.jsonrpc.context.JSONRPCContextKeys.METHOD_NAME_KEY; |
7 | 15 | import static io.a2a.transport.jsonrpc.context.JSONRPCContextKeys.TENANT_KEY; |
8 | 16 | import static java.util.Collections.singletonList; |
| 17 | +import static io.vertx.core.http.HttpHeaders.CONTENT_TYPE; |
| 18 | +import static jakarta.ws.rs.core.MediaType.APPLICATION_JSON; |
9 | 19 | import static org.junit.jupiter.api.Assertions.assertEquals; |
10 | 20 | import static org.junit.jupiter.api.Assertions.assertNotNull; |
11 | 21 | import static org.mockito.ArgumentMatchers.any; |
|
59 | 69 | import org.junit.jupiter.api.Test; |
60 | 70 | import org.mockito.ArgumentCaptor; |
61 | 71 |
|
62 | | -import static io.a2a.spec.A2AMethods.DELETE_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; |
63 | | -import static io.a2a.spec.A2AMethods.GET_TASK_METHOD; |
64 | | -import static io.a2a.spec.A2AMethods.GET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; |
65 | | -import static io.a2a.spec.A2AMethods.LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; |
66 | | -import static io.a2a.spec.A2AMethods.SEND_MESSAGE_METHOD; |
67 | | -import static io.a2a.spec.A2AMethods.SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; |
68 | | -import static io.a2a.spec.A2AMethods.SUBSCRIBE_TO_TASK_METHOD; |
69 | | - |
70 | 72 | /** |
71 | 73 | * Unit test for JSON-RPC A2AServerRoutes that verifies the method names are properly set |
72 | 74 | * in the ServerCallContext for all request types. |
@@ -166,6 +168,7 @@ public void testSendMessage_MethodNameSetInContext() { |
166 | 168 | ServerCallContext capturedContext = contextCaptor.getValue(); |
167 | 169 | assertNotNull(capturedContext); |
168 | 170 | assertEquals(SEND_MESSAGE_METHOD, capturedContext.getState().get(METHOD_NAME_KEY)); |
| 171 | + verify(mockHttpResponse).putHeader(CONTENT_TYPE, APPLICATION_JSON); |
169 | 172 | } |
170 | 173 |
|
171 | 174 | @Test |
@@ -250,6 +253,7 @@ public void testGetTask_MethodNameSetInContext() { |
250 | 253 | ServerCallContext capturedContext = contextCaptor.getValue(); |
251 | 254 | assertNotNull(capturedContext); |
252 | 255 | assertEquals(GET_TASK_METHOD, capturedContext.getState().get(METHOD_NAME_KEY)); |
| 256 | + verify(mockHttpResponse).putHeader(CONTENT_TYPE, APPLICATION_JSON); |
253 | 257 | } |
254 | 258 |
|
255 | 259 | @Test |
@@ -286,6 +290,7 @@ public void testCancelTask_MethodNameSetInContext() { |
286 | 290 | ServerCallContext capturedContext = contextCaptor.getValue(); |
287 | 291 | assertNotNull(capturedContext); |
288 | 292 | assertEquals(CANCEL_TASK_METHOD, capturedContext.getState().get(METHOD_NAME_KEY)); |
| 293 | + verify(mockHttpResponse).putHeader(CONTENT_TYPE, APPLICATION_JSON); |
289 | 294 | } |
290 | 295 |
|
291 | 296 | @Test |
@@ -363,6 +368,7 @@ public void testCreateTaskPushNotificationConfig_MethodNameSetInContext() { |
363 | 368 | ServerCallContext capturedContext = contextCaptor.getValue(); |
364 | 369 | assertNotNull(capturedContext); |
365 | 370 | assertEquals(SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD, capturedContext.getState().get(METHOD_NAME_KEY)); |
| 371 | + verify(mockHttpResponse).putHeader(CONTENT_TYPE, APPLICATION_JSON); |
366 | 372 | } |
367 | 373 |
|
368 | 374 | @Test |
@@ -401,6 +407,7 @@ public void testGetTaskPushNotificationConfig_MethodNameSetInContext() { |
401 | 407 | ServerCallContext capturedContext = contextCaptor.getValue(); |
402 | 408 | assertNotNull(capturedContext); |
403 | 409 | assertEquals(GET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD, capturedContext.getState().get(METHOD_NAME_KEY)); |
| 410 | + verify(mockHttpResponse).putHeader(CONTENT_TYPE, APPLICATION_JSON); |
404 | 411 | } |
405 | 412 |
|
406 | 413 | @Test |
@@ -440,6 +447,7 @@ public void testListTaskPushNotificationConfig_MethodNameSetInContext() { |
440 | 447 | ServerCallContext capturedContext = contextCaptor.getValue(); |
441 | 448 | assertNotNull(capturedContext); |
442 | 449 | assertEquals(LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD, capturedContext.getState().get(METHOD_NAME_KEY)); |
| 450 | + verify(mockHttpResponse).putHeader(CONTENT_TYPE, APPLICATION_JSON); |
443 | 451 | } |
444 | 452 |
|
445 | 453 | @Test |
@@ -473,6 +481,7 @@ public void testDeleteTaskPushNotificationConfig_MethodNameSetInContext() { |
473 | 481 | ServerCallContext capturedContext = contextCaptor.getValue(); |
474 | 482 | assertNotNull(capturedContext); |
475 | 483 | assertEquals(DELETE_TASK_PUSH_NOTIFICATION_CONFIG_METHOD, capturedContext.getState().get(METHOD_NAME_KEY)); |
| 484 | + verify(mockHttpResponse).putHeader(CONTENT_TYPE, APPLICATION_JSON); |
476 | 485 | } |
477 | 486 |
|
478 | 487 | @Test |
@@ -509,6 +518,7 @@ public void testGetExtendedCard_MethodNameSetInContext() { |
509 | 518 | ServerCallContext capturedContext = contextCaptor.getValue(); |
510 | 519 | assertNotNull(capturedContext); |
511 | 520 | assertEquals(GET_EXTENDED_AGENT_CARD_METHOD, capturedContext.getState().get(METHOD_NAME_KEY)); |
| 521 | + verify(mockHttpResponse).putHeader(CONTENT_TYPE, APPLICATION_JSON); |
512 | 522 | } |
513 | 523 |
|
514 | 524 | @Test |
@@ -707,6 +717,38 @@ public void testTenantExtraction_StreamingRequest() { |
707 | 717 | assertEquals("myTenant/api", capturedContext.getState().get(TENANT_KEY)); |
708 | 718 | } |
709 | 719 |
|
| 720 | + @Test |
| 721 | + public void testJsonParseError_ContentTypeIsProblemJson() { |
| 722 | + // Arrange - invalid JSON |
| 723 | + String invalidJson = "not valid json {{{"; |
| 724 | + when(mockRequestBody.asString()).thenReturn(invalidJson); |
| 725 | + |
| 726 | + // Act |
| 727 | + routes.invokeJSONRPCHandler(invalidJson, mockRoutingContext); |
| 728 | + |
| 729 | + // Assert |
| 730 | + verify(mockHttpResponse).putHeader(CONTENT_TYPE, APPLICATION_PROBLEM_JSON); |
| 731 | + } |
| 732 | + |
| 733 | + @Test |
| 734 | + public void testMethodNotFound_ContentTypeIsProblemJson() { |
| 735 | + // Arrange - unknown method |
| 736 | + String jsonRpcRequest = """ |
| 737 | + { |
| 738 | + "jsonrpc": "2.0", |
| 739 | + "id": "cd4c76de-d54c-436c-8b9f-4c2703648d64", |
| 740 | + "method": "UnknownMethod", |
| 741 | + "params": {} |
| 742 | + }"""; |
| 743 | + when(mockRequestBody.asString()).thenReturn(jsonRpcRequest); |
| 744 | + |
| 745 | + // Act |
| 746 | + routes.invokeJSONRPCHandler(jsonRpcRequest, mockRoutingContext); |
| 747 | + |
| 748 | + // Assert |
| 749 | + verify(mockHttpResponse).putHeader(CONTENT_TYPE, APPLICATION_PROBLEM_JSON); |
| 750 | + } |
| 751 | + |
710 | 752 | /** |
711 | 753 | * Helper method to set a field via reflection for testing purposes. |
712 | 754 | */ |
|
0 commit comments