a2a-test-framework 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. checksums.yaml +7 -0
  2. data/a2a.json +1961 -0
  3. data/a2a.proto +796 -0
  4. data/endpoints/grpc/cancel_task.json +10 -0
  5. data/endpoints/grpc/create_task_push_notification_config.json +10 -0
  6. data/endpoints/grpc/delete_task_push_notification_config.json +10 -0
  7. data/endpoints/grpc/get_extended_agent_card.json +10 -0
  8. data/endpoints/grpc/get_task.json +10 -0
  9. data/endpoints/grpc/get_task_push_notification_config.json +10 -0
  10. data/endpoints/grpc/list_task_push_notification_configs.json +10 -0
  11. data/endpoints/grpc/list_tasks.json +10 -0
  12. data/endpoints/grpc/send_message.json +10 -0
  13. data/endpoints/grpc/send_streaming_message.json +10 -0
  14. data/endpoints/grpc/subscribe_to_task.json +10 -0
  15. data/endpoints/rest/cancel_task.json +85 -0
  16. data/endpoints/rest/create_task_push_notification_config.json +104 -0
  17. data/endpoints/rest/delete_task_push_notification_config.json +46 -0
  18. data/endpoints/rest/get_extended_agent_card.json +168 -0
  19. data/endpoints/rest/get_task.json +111 -0
  20. data/endpoints/rest/get_task_push_notification_config.json +90 -0
  21. data/endpoints/rest/list_task_push_notification_configs.json +108 -0
  22. data/endpoints/rest/list_tasks.json +239 -0
  23. data/endpoints/rest/send_message.json +57 -0
  24. data/endpoints/rest/send_streaming_message.json +75 -0
  25. data/endpoints/rest/subscribe_to_task.json +68 -0
  26. data/exe/a2a-test +6 -0
  27. data/lib/a2a_test_framework/cli.rb +190 -0
  28. data/lib/a2a_test_framework/sse_client.rb +104 -0
  29. data/lib/a2a_test_framework/test_helper.rb +146 -0
  30. data/lib/a2a_test_framework/version.rb +5 -0
  31. data/lib/a2a_test_framework.rb +17 -0
  32. data/tests/grpc/cancel_task_test.rb +69 -0
  33. data/tests/grpc/create_task_push_notification_config_test.rb +79 -0
  34. data/tests/grpc/delete_task_push_notification_config_test.rb +54 -0
  35. data/tests/grpc/error_code_mappings_test.rb +39 -0
  36. data/tests/grpc/error_handling_test.rb +175 -0
  37. data/tests/grpc/get_extended_agent_card_test.rb +83 -0
  38. data/tests/grpc/get_task_push_notification_config_test.rb +39 -0
  39. data/tests/grpc/get_task_test.rb +76 -0
  40. data/tests/grpc/grpc_binding_test.rb +74 -0
  41. data/tests/grpc/list_task_push_notification_configs_test.rb +53 -0
  42. data/tests/grpc/list_tasks_test.rb +117 -0
  43. data/tests/grpc/protocol_data_model_test.rb +14 -0
  44. data/tests/grpc/send_message_test.rb +141 -0
  45. data/tests/grpc/send_streaming_message_test.rb +122 -0
  46. data/tests/grpc/streaming_event_delivery_test.rb +48 -0
  47. data/tests/grpc/subscribe_to_task_test.rb +92 -0
  48. data/tests/grpc/versioning_test.rb +32 -0
  49. data/tests/rest/agent_card_caching_test.rb +39 -0
  50. data/tests/rest/agent_card_signing_test.rb +74 -0
  51. data/tests/rest/agent_discovery_test.rb +117 -0
  52. data/tests/rest/authentication_authorization_test.rb +62 -0
  53. data/tests/rest/cancel_task_test.rb +110 -0
  54. data/tests/rest/capability_validation_test.rb +78 -0
  55. data/tests/rest/context_identifier_semantics_test.rb +75 -0
  56. data/tests/rest/create_task_push_notification_config_test.rb +122 -0
  57. data/tests/rest/custom_binding_test.rb +96 -0
  58. data/tests/rest/delete_task_push_notification_config_test.rb +103 -0
  59. data/tests/rest/error_code_mappings_test.rb +45 -0
  60. data/tests/rest/error_handling_test.rb +178 -0
  61. data/tests/rest/extension_versioning_test.rb +44 -0
  62. data/tests/rest/field_presence_optionality_test.rb +64 -0
  63. data/tests/rest/functional_equivalence_test.rb +23 -0
  64. data/tests/rest/get_extended_agent_card_test.rb +67 -0
  65. data/tests/rest/get_task_push_notification_config_test.rb +75 -0
  66. data/tests/rest/get_task_test.rb +134 -0
  67. data/tests/rest/history_length_semantics_test.rb +91 -0
  68. data/tests/rest/http_rest_binding_test.rb +114 -0
  69. data/tests/rest/iana_registrations_test.rb +47 -0
  70. data/tests/rest/idempotency_test.rb +69 -0
  71. data/tests/rest/in_task_authorization_test.rb +45 -0
  72. data/tests/rest/json_field_naming_test.rb +89 -0
  73. data/tests/rest/json_rpc_binding_test.rb +102 -0
  74. data/tests/rest/list_task_push_notification_configs_test.rb +92 -0
  75. data/tests/rest/list_tasks_test.rb +162 -0
  76. data/tests/rest/messages_and_artifacts_test.rb +101 -0
  77. data/tests/rest/multi_turn_conversation_test.rb +94 -0
  78. data/tests/rest/protocol_data_model_test.rb +99 -0
  79. data/tests/rest/protocol_security_test.rb +25 -0
  80. data/tests/rest/protocol_selection_negotiation_test.rb +24 -0
  81. data/tests/rest/push_notification_delivery_test.rb +115 -0
  82. data/tests/rest/security_considerations_test.rb +101 -0
  83. data/tests/rest/send_message_test.rb +230 -0
  84. data/tests/rest/send_streaming_message_test.rb +129 -0
  85. data/tests/rest/service_parameters_test.rb +52 -0
  86. data/tests/rest/streaming_event_delivery_test.rb +58 -0
  87. data/tests/rest/subscribe_to_task_test.rb +99 -0
  88. data/tests/rest/task_identifier_semantics_test.rb +67 -0
  89. data/tests/rest/timestamps_test.rb +70 -0
  90. data/tests/rest/versioning_responsibilities_test.rb +46 -0
  91. data/tests/rest/versioning_test.rb +44 -0
  92. metadata +159 -0
@@ -0,0 +1,141 @@
1
+ require "a2a_test_framework/test_helper"
2
+
3
+ # NOTE: All tests commented out -- gRPC binding not supported by reference server
4
+
5
+ # require "a2a_test_framework/test_helper"
6
+
7
+ # # NOTE: All tests commented out -- gRPC binding not supported by reference server
8
+
9
+ # # describe "A2AService/SendMessage" do
10
+ # # # --- Response Type Behavior ---
11
+ # #
12
+ # # describe "when a client sends a SendMessageRequest with a valid message" do
13
+ # # it "should respond with a Task object containing a valid task ID and status" do
14
+ # # end
15
+ # #
16
+ # # it "should return either a Task or a Message, never both" do
17
+ # # end
18
+ # #
19
+ # # it "should return immediately without blocking on task completion" do
20
+ # # end
21
+ # # end
22
+ # #
23
+ # # describe "when a client sends a SendMessageRequest with a simple message" do
24
+ # # it "should respond with a Message object containing a role" do
25
+ # # end
26
+ # #
27
+ # # it "should respond with a Message object containing one or more Parts" do
28
+ # # end
29
+ # # end
30
+ # #
31
+ # # describe "when the server creates a Task to process the message asynchronously" do
32
+ # # it "should return a Task that MAY be in a non-terminal state" do
33
+ # # end
34
+ # #
35
+ # # it "should allow task processing to continue after response is returned" do
36
+ # # end
37
+ # # end
38
+ # #
39
+ # # # --- Response Structure Validation ---
40
+ # #
41
+ # # describe "when validating the response structure" do
42
+ # # it "should contain exactly one of Task or Message" do
43
+ # # end
44
+ # #
45
+ # # it "should never contain both a Task and a Message simultaneously" do
46
+ # # end
47
+ # # end
48
+ # #
49
+ # # # --- Error Cases ---
50
+ # #
51
+ # # describe "when a client sends a Part with an unsupported media type" do
52
+ # # it "should respond with a ContentTypeNotSupportedError" do
53
+ # # end
54
+ # # end
55
+ # #
56
+ # # describe "when a client sends a SendMessageRequest referencing a completed task" do
57
+ # # it "should respond with an UnsupportedOperationError" do
58
+ # # end
59
+ # # end
60
+ # #
61
+ # # describe "when a client sends a SendMessageRequest referencing a canceled task" do
62
+ # # it "should respond with an UnsupportedOperationError" do
63
+ # # end
64
+ # # end
65
+ # #
66
+ # # describe "when a client sends a SendMessageRequest referencing a rejected task" do
67
+ # # it "should respond with an UnsupportedOperationError" do
68
+ # # end
69
+ # # end
70
+ # #
71
+ # # describe "when a client sends a SendMessageRequest referencing a non-existent task ID" do
72
+ # # it "should respond with a TaskNotFoundError" do
73
+ # # end
74
+ # # end
75
+ # #
76
+ # # describe "when a client sends a SendMessageRequest referencing a task not accessible to the client" do
77
+ # # it "should respond with a TaskNotFoundError" do
78
+ # # end
79
+ # # end
80
+ # #
81
+ # # # --- SendMessageConfiguration: Blocking Mode (Default) ---
82
+ # #
83
+ # # describe "when a client sends a SendMessageRequest with return_immediately unset (blocking mode)" do
84
+ # # it "should wait until the task reaches completed state before returning" do
85
+ # # end
86
+ # #
87
+ # # it "should wait until the task reaches failed state before returning" do
88
+ # # end
89
+ # #
90
+ # # it "should wait until the task reaches canceled state before returning" do
91
+ # # end
92
+ # #
93
+ # # it "should wait until the task reaches rejected state before returning" do
94
+ # # end
95
+ # #
96
+ # # it "should wait until the task reaches input_required state before returning" do
97
+ # # end
98
+ # #
99
+ # # it "should wait until the task reaches auth_required state before returning" do
100
+ # # end
101
+ # #
102
+ # # it "should include the latest task state with all artifacts and status information" do
103
+ # # end
104
+ # #
105
+ # # it "should behave in blocking mode by default when return_immediately is not specified" do
106
+ # # end
107
+ # # end
108
+ # #
109
+ # # # --- SendMessageConfiguration: Non-Blocking Mode ---
110
+ # #
111
+ # # describe "when a client sends a SendMessageRequest with return_immediately set to true" do
112
+ # # it "should return immediately after creating the task" do
113
+ # # end
114
+ # #
115
+ # # it "should not wait for the task to reach a terminal state" do
116
+ # # end
117
+ # #
118
+ # # it "should return a task in an in-progress state" do
119
+ # # end
120
+ # #
121
+ # # it "should require the client to poll for updates using GetTask or subscribe" do
122
+ # # end
123
+ # # end
124
+ # #
125
+ # # # --- SendMessageConfiguration: No Effect Cases ---
126
+ # #
127
+ # # describe "when return_immediately is set but the agent returns a direct Message" do
128
+ # # it "should have no effect on the response behavior" do
129
+ # # end
130
+ # # end
131
+ # #
132
+ # # describe "when return_immediately is set on a streaming operation" do
133
+ # # it "should have no effect on the streaming behavior" do
134
+ # # end
135
+ # # end
136
+ # #
137
+ # # describe "when return_immediately is set and push notifications are configured" do
138
+ # # it "should operate push notification delivery independently of execution mode" do
139
+ # # end
140
+ # # end
141
+ # # end
@@ -0,0 +1,122 @@
1
+ require "a2a_test_framework/test_helper"
2
+
3
+ # NOTE: All tests commented out -- gRPC binding not supported by reference server
4
+
5
+ # require "a2a_test_framework/test_helper"
6
+
7
+ # # NOTE: All tests commented out -- gRPC binding not supported by reference server
8
+
9
+ # # describe "A2AService/SendStreamingMessage" do
10
+ # # # --- Streaming Connection Establishment ---
11
+ # #
12
+ # # describe "when a client sends a SendStreamingMessage request with a valid message" do
13
+ # # it "should establish a server-streaming connection for real-time updates" do
14
+ # # end
15
+ # # end
16
+ # #
17
+ # # # --- Message-Only Stream Pattern ---
18
+ # #
19
+ # # describe "when the agent returns a Message response via stream" do
20
+ # # it "should contain exactly one Message object in the stream" do
21
+ # # end
22
+ # #
23
+ # # it "should close the stream immediately after the Message" do
24
+ # # end
25
+ # #
26
+ # # it "should not contain any TaskStatusUpdateEvent objects" do
27
+ # # end
28
+ # #
29
+ # # it "should not contain any TaskArtifactUpdateEvent objects" do
30
+ # # end
31
+ # #
32
+ # # it "should not contain any Task objects" do
33
+ # # end
34
+ # # end
35
+ # #
36
+ # # # --- Task Lifecycle Stream Pattern ---
37
+ # #
38
+ # # describe "when the agent returns a Task response via stream" do
39
+ # # it "should send a Task object as the first item in the stream" do
40
+ # # end
41
+ # #
42
+ # # it "should follow the Task with TaskStatusUpdateEvent objects" do
43
+ # # end
44
+ # #
45
+ # # it "should follow the Task with TaskArtifactUpdateEvent objects" do
46
+ # # end
47
+ # # end
48
+ # #
49
+ # # describe "when the task reaches a terminal state during streaming" do
50
+ # # it "should close the stream when task reaches completed state" do
51
+ # # end
52
+ # #
53
+ # # it "should close the stream when task reaches failed state" do
54
+ # # end
55
+ # #
56
+ # # it "should close the stream when task reaches canceled state" do
57
+ # # end
58
+ # #
59
+ # # it "should close the stream when task reaches rejected state" do
60
+ # # end
61
+ # #
62
+ # # it "should not close the stream while task is in working state" do
63
+ # # end
64
+ # # end
65
+ # #
66
+ # # # --- Immediate Feedback Requirement ---
67
+ # #
68
+ # # describe "when a client is consuming a stream" do
69
+ # # it "should provide immediate feedback on progress" do
70
+ # # end
71
+ # #
72
+ # # it "should deliver intermediate results as they become available" do
73
+ # # end
74
+ # # end
75
+ # #
76
+ # # # --- Error Cases ---
77
+ # #
78
+ # # describe "when the server does not support streaming" do
79
+ # # it "should respond with an UnsupportedOperationError" do
80
+ # # end
81
+ # # end
82
+ # #
83
+ # # describe "when a client sends a streaming request referencing a completed task" do
84
+ # # it "should respond with an UnsupportedOperationError" do
85
+ # # end
86
+ # # end
87
+ # #
88
+ # # describe "when a client sends a streaming request referencing a canceled task" do
89
+ # # it "should respond with an UnsupportedOperationError" do
90
+ # # end
91
+ # # end
92
+ # #
93
+ # # describe "when a client sends a streaming request referencing a rejected task" do
94
+ # # it "should respond with an UnsupportedOperationError" do
95
+ # # end
96
+ # # end
97
+ # #
98
+ # # describe "when a client sends a streaming request with an unsupported media type" do
99
+ # # it "should respond with a ContentTypeNotSupportedError" do
100
+ # # end
101
+ # # end
102
+ # #
103
+ # # describe "when a client sends a streaming request referencing a non-existent task ID" do
104
+ # # it "should respond with a TaskNotFoundError" do
105
+ # # end
106
+ # # end
107
+ # #
108
+ # # describe "when a client sends a streaming request referencing a task not accessible to the client" do
109
+ # # it "should respond with a TaskNotFoundError" do
110
+ # # end
111
+ # # end
112
+ # #
113
+ # # # --- Stream Response Structure ---
114
+ # #
115
+ # # describe "when validating the stream initial response structure" do
116
+ # # it "should contain exactly one of Task or Message as initial response" do
117
+ # # end
118
+ # #
119
+ # # it "should never contain both Task and Message as initial response" do
120
+ # # end
121
+ # # end
122
+ # # end
@@ -0,0 +1,48 @@
1
+ require "a2a_test_framework/test_helper"
2
+
3
+ # NOTE: All tests commented out -- gRPC binding not supported by reference server
4
+
5
+ # require "a2a_test_framework/test_helper"
6
+
7
+ # # NOTE: All tests commented out -- gRPC binding not supported by reference server
8
+
9
+ # # describe "Streaming Event Delivery (gRPC)" do
10
+ # # # --- Event Ordering ---
11
+ # #
12
+ # # describe "when a task generates multiple events in sequence" do
13
+ # # it "should deliver all events in the order they were generated" do
14
+ # # end
15
+ # #
16
+ # # it "should not reorder events during transmission" do
17
+ # # end
18
+ # #
19
+ # # it "should preserve event ordering regardless of protocol binding" do
20
+ # # end
21
+ # # end
22
+ # #
23
+ # # # --- Multiple Streams Per Task ---
24
+ # #
25
+ # # describe "when multiple clients subscribe to the same task" do
26
+ # # it "should serve multiple concurrent streams simultaneously" do
27
+ # # end
28
+ # #
29
+ # # it "should broadcast events to all active streams for a task" do
30
+ # # end
31
+ # #
32
+ # # it "should deliver the same events in the same order to each stream" do
33
+ # # end
34
+ # # end
35
+ # #
36
+ # # describe "when one client closes their stream" do
37
+ # # it "should keep other active streams open and receiving events" do
38
+ # # end
39
+ # #
40
+ # # it "should not affect the task lifecycle" do
41
+ # # end
42
+ # # end
43
+ # #
44
+ # # describe "when a single client opens two subscription streams for the same task" do
45
+ # # it "should deliver events to both streams" do
46
+ # # end
47
+ # # end
48
+ # # end
@@ -0,0 +1,92 @@
1
+ require "a2a_test_framework/test_helper"
2
+
3
+ # NOTE: All tests commented out -- gRPC binding not supported by reference server
4
+
5
+ # require "a2a_test_framework/test_helper"
6
+
7
+ # # NOTE: All tests commented out -- gRPC binding not supported by reference server
8
+
9
+ # # describe "A2AService/SubscribeToTask" do
10
+ # # # --- Stream Initialization ---
11
+ # #
12
+ # # describe "when a client subscribes to a working task" do
13
+ # # it "should send a Task object as the first event in the stream" do
14
+ # # end
15
+ # #
16
+ # # it "should represent the current state of the task at time of subscription" do
17
+ # # end
18
+ # #
19
+ # # it "should not require a separate GetTask call to avoid missing updates" do
20
+ # # end
21
+ # # end
22
+ # #
23
+ # # # --- Stream Content ---
24
+ # #
25
+ # # describe "when the subscribed task status changes" do
26
+ # # it "should deliver a TaskStatusUpdateEvent object" do
27
+ # # end
28
+ # # end
29
+ # #
30
+ # # describe "when the subscribed task generates a new artifact" do
31
+ # # it "should deliver a TaskArtifactUpdateEvent object" do
32
+ # # end
33
+ # # end
34
+ # #
35
+ # # # --- Stream Termination ---
36
+ # #
37
+ # # describe "when the subscribed task reaches a terminal state" do
38
+ # # it "should terminate the stream when task reaches completed state" do
39
+ # # end
40
+ # #
41
+ # # it "should terminate the stream when task reaches failed state" do
42
+ # # end
43
+ # #
44
+ # # it "should terminate the stream when task reaches canceled state" do
45
+ # # end
46
+ # #
47
+ # # it "should terminate the stream when task reaches rejected state" do
48
+ # # end
49
+ # # end
50
+ # #
51
+ # # describe "when the subscribed task is in a non-terminal state" do
52
+ # # it "should keep the stream open while task is in working state" do
53
+ # # end
54
+ # # end
55
+ # #
56
+ # # # --- Error Cases ---
57
+ # #
58
+ # # describe "when the server does not support streaming" do
59
+ # # it "should respond with an UnsupportedOperationError" do
60
+ # # end
61
+ # # end
62
+ # #
63
+ # # describe "when a client subscribes to a non-existent task ID" do
64
+ # # it "should respond with a TaskNotFoundError" do
65
+ # # end
66
+ # # end
67
+ # #
68
+ # # describe "when a client subscribes to a task not accessible to the client" do
69
+ # # it "should respond with a TaskNotFoundError" do
70
+ # # end
71
+ # # end
72
+ # #
73
+ # # describe "when a client subscribes to a task in completed state" do
74
+ # # it "should respond with an UnsupportedOperationError" do
75
+ # # end
76
+ # # end
77
+ # #
78
+ # # describe "when a client subscribes to a task in failed state" do
79
+ # # it "should respond with an UnsupportedOperationError" do
80
+ # # end
81
+ # # end
82
+ # #
83
+ # # describe "when a client subscribes to a task in canceled state" do
84
+ # # it "should respond with an UnsupportedOperationError" do
85
+ # # end
86
+ # # end
87
+ # #
88
+ # # describe "when a client subscribes to a task in rejected state" do
89
+ # # it "should respond with an UnsupportedOperationError" do
90
+ # # end
91
+ # # end
92
+ # # end
@@ -0,0 +1,32 @@
1
+ require "a2a_test_framework/test_helper"
2
+
3
+ # NOTE: All tests commented out -- gRPC binding not supported by reference server
4
+
5
+ # require "a2a_test_framework/test_helper"
6
+
7
+ # # NOTE: All tests commented out -- gRPC binding not supported by reference server
8
+
9
+ # # describe "Protocol Versioning (gRPC)" do
10
+ # # # --- Version Format ---
11
+ # #
12
+ # # describe "when a client sends a request with a2a-version metadata" do
13
+ # # it "should recognize Major.Minor format as valid" do
14
+ # # end
15
+ # #
16
+ # # it "should not require patch version numbers" do
17
+ # # end
18
+ # # end
19
+ # #
20
+ # # describe "when the server returns version information" do
21
+ # # it "should not include patch version numbers" do
22
+ # # end
23
+ # # end
24
+ # #
25
+ # # describe "when performing version negotiation" do
26
+ # # it "should not consider patch version differences" do
27
+ # # end
28
+ # #
29
+ # # it "should treat versions differing only by patch as compatible" do
30
+ # # end
31
+ # # end
32
+ # # end
@@ -0,0 +1,39 @@
1
+ require "a2a_test_framework/test_helper"
2
+
3
+ # NOTE: All tests commented out -- Reference server does not implement caching headers
4
+
5
+ # require "a2a_test_framework/test_helper"
6
+
7
+ # # NOTE: All tests commented out -- Reference server does not implement caching headers
8
+
9
+ # # describe "Agent Card Caching (REST)" do
10
+ # # # --- Server Requirements ---
11
+ # #
12
+ # # describe "when a client fetches the Agent Card" do
13
+ # # it "should include a Cache-Control header with a max-age directive" do
14
+ # # end
15
+ # #
16
+ # # it "should include an ETag header derived from version or content hash" do
17
+ # # end
18
+ # #
19
+ # # it "should MAY include a Last-Modified header" do
20
+ # # end
21
+ # # end
22
+ # #
23
+ # # # --- Client Requirements ---
24
+ # #
25
+ # # describe "when a client caches the Agent Card" do
26
+ # # it "should honor HTTP caching semantics as defined in RFC 9111" do
27
+ # # end
28
+ # # end
29
+ # #
30
+ # # describe "when a client has an expired cached Agent Card" do
31
+ # # it "should use conditional requests with If-None-Match or If-Modified-Since" do
32
+ # # end
33
+ # # end
34
+ # #
35
+ # # describe "when the server does not include caching headers" do
36
+ # # it "should MAY apply an implementation-specific default cache duration" do
37
+ # # end
38
+ # # end
39
+ # # end
@@ -0,0 +1,74 @@
1
+ require "a2a_test_framework/test_helper"
2
+
3
+ # NOTE: All tests commented out -- Reference server does not implement agent card signing
4
+
5
+ # require "a2a_test_framework/test_helper"
6
+
7
+ # # NOTE: All tests commented out -- Reference server does not implement agent card signing
8
+
9
+ # # describe "Agent Card Signing (REST)" do
10
+ # # # --- Canonicalization Requirements ---
11
+ # #
12
+ # # describe "when an Agent Card is signed" do
13
+ # # it "should canonicalize content using JCS (RFC 8785) before signing" do
14
+ # # end
15
+ # #
16
+ # # it "should omit optional fields not explicitly set before canonicalization" do
17
+ # # end
18
+ # #
19
+ # # it "should include optional fields explicitly set to defaults" do
20
+ # # end
21
+ # #
22
+ # # it "should always include required fields in canonical form" do
23
+ # # end
24
+ # #
25
+ # # it "should order properties lexicographically per RFC 8785" do
26
+ # # end
27
+ # #
28
+ # # it "should remove insignificant whitespace per RFC 8785" do
29
+ # # end
30
+ # #
31
+ # # it "should exclude the signatures field from content being signed" do
32
+ # # end
33
+ # # end
34
+ # #
35
+ # # # --- Signature Format ---
36
+ # #
37
+ # # describe "when validating a signed Agent Card" do
38
+ # # it "should include alg parameter in JWS protected header" do
39
+ # # end
40
+ # #
41
+ # # it "should include kid parameter in JWS protected header" do
42
+ # # end
43
+ # #
44
+ # # it "should have typ set to JOSE in the protected header" do
45
+ # # end
46
+ # #
47
+ # # it "should have a base64url-encoded JSON protected field" do
48
+ # # end
49
+ # #
50
+ # # it "should have a base64url-encoded signature value" do
51
+ # # end
52
+ # # end
53
+ # #
54
+ # # # --- Signature Verification ---
55
+ # #
56
+ # # describe "when a client verifies an Agent Card signature" do
57
+ # # it "should follow verification steps in order" do
58
+ # # end
59
+ # #
60
+ # # it "should verify at least one signature before trusting the Agent Card" do
61
+ # # end
62
+ # #
63
+ # # it "should retrieve public keys over HTTPS" do
64
+ # # end
65
+ # #
66
+ # # it "should not use expired or revoked keys for verification" do
67
+ # # end
68
+ # # end
69
+ # #
70
+ # # describe "when an Agent Card has multiple signatures" do
71
+ # # it "should accept multiple signatures for key rotation support" do
72
+ # # end
73
+ # # end
74
+ # # end
@@ -0,0 +1,117 @@
1
+ require "a2a_test_framework/test_helper"
2
+
3
+ # Agent discovery: well-known URI and AgentCard structure
4
+
5
+ describe "Agent Discovery (REST)" do
6
+ # --- Purpose ---
7
+
8
+ describe "when a server is running" do
9
+ it "should make an Agent Card available at the well-known URI" do
10
+ response = http_get("/.well-known/agent-card.json")
11
+ response.code.to_i.should.equal 200
12
+ end
13
+
14
+ it "should describe identity, capabilities, skills, and interaction requirements" do
15
+ response = http_get("/.well-known/agent-card.json")
16
+ data = parse_json(response)
17
+
18
+ # Identity
19
+ data["name"].should.not.be.nil
20
+ data["name"].should.be.kind_of String
21
+ data["version"].should.not.be.nil
22
+
23
+ # Capabilities
24
+ data["capabilities"].should.not.be.nil
25
+ data["capabilities"].should.be.kind_of Hash
26
+
27
+ # Skills
28
+ data["skills"].should.not.be.nil
29
+ data["skills"].should.be.kind_of Array
30
+ data["skills"].length.should.be > 0
31
+ end
32
+ end
33
+
34
+ # --- Discovery Mechanisms ---
35
+
36
+ describe "when a client requests the well-known Agent Card URI" do
37
+ it "should return the Agent Card as JSON from /.well-known/agent-card.json" do
38
+ response = http_get("/.well-known/agent-card.json")
39
+ response.code.to_i.should.equal 200
40
+
41
+ content_type = response["Content-Type"].to_s
42
+ content_type.should.include "json"
43
+
44
+ data = parse_json(response)
45
+ data.should.be.kind_of Hash
46
+ data["name"].should.not.be.nil
47
+ end
48
+ end
49
+
50
+ # --- Supported Interfaces Declaration ---
51
+
52
+ describe "when the AgentCard declares supportedInterfaces" do
53
+ it "should declare supported protocol combinations" do
54
+ response = http_get("/.well-known/agent-card.json")
55
+ data = parse_json(response)
56
+
57
+ data["supportedInterfaces"].should.not.be.nil
58
+ data["supportedInterfaces"].should.be.kind_of Array
59
+ data["supportedInterfaces"].length.should.be > 0
60
+ end
61
+
62
+ it "should include protocolBinding and url for each interface" do
63
+ response = http_get("/.well-known/agent-card.json")
64
+ data = parse_json(response)
65
+
66
+ data["supportedInterfaces"].each do |iface|
67
+ iface["url"].should.not.be.nil
68
+ iface["protocolBinding"].should.not.be.nil
69
+ end
70
+ end
71
+ end
72
+
73
+ # --- AgentCard Structure ---
74
+
75
+ describe "when validating AgentCard structure" do
76
+ it "should include a name field" do
77
+ response = http_get("/.well-known/agent-card.json")
78
+ data = parse_json(response)
79
+ data["name"].should.be.kind_of String
80
+ data["name"].length.should.be > 0
81
+ end
82
+
83
+ it "should include a version field" do
84
+ response = http_get("/.well-known/agent-card.json")
85
+ data = parse_json(response)
86
+ data["version"].should.be.kind_of String
87
+ data["version"].length.should.be > 0
88
+ end
89
+
90
+ it "should include capabilities with boolean fields" do
91
+ response = http_get("/.well-known/agent-card.json")
92
+ data = parse_json(response)
93
+
94
+ caps = data["capabilities"]
95
+ caps.key?("streaming").should.equal true
96
+ caps.key?("pushNotifications").should.equal true
97
+ end
98
+
99
+ it "should include skills with required fields" do
100
+ response = http_get("/.well-known/agent-card.json")
101
+ data = parse_json(response)
102
+
103
+ skill = data["skills"].first
104
+ skill["id"].should.not.be.nil
105
+ skill["name"].should.not.be.nil
106
+ skill["description"].should.not.be.nil
107
+ end
108
+ end
109
+
110
+ # --- Client Protocol Selection ---
111
+ # NOTE: Commented out -- behavioral requirement, not testable against single server
112
+
113
+ # describe "when a client parses supportedInterfaces" do
114
+ # it "should select the first supported transport from the list" do
115
+ # end
116
+ # end
117
+ end