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,67 @@
1
+ require "a2a_test_framework/test_helper"
2
+
3
+ # Cross-cutting: Task identifier semantics
4
+
5
+ describe "Task Identifier Semantics (REST)" do
6
+ # --- Server Generation ---
7
+
8
+ describe "when a client sends a message that triggers task creation" do
9
+ it "should generate the taskId on the server" do
10
+ body = build_send_message_request(text: "Task ID generation")
11
+ response = http_post("/message:send", body)
12
+ data = parse_json(response)
13
+
14
+ if data["task"]
15
+ data["task"]["id"].should.not.be.nil
16
+ data["task"]["id"].should.be.kind_of String
17
+ data["task"]["id"].length.should.be > 0
18
+ end
19
+ true.should.equal true
20
+ end
21
+ end
22
+
23
+ describe "when multiple tasks are created" do
24
+ it "should generate a unique taskId for each new task" do
25
+ task1 = create_task!(text: "Unique ID test 1")
26
+ task2 = create_task!(text: "Unique ID test 2")
27
+
28
+ task1["id"].should.not.equal task2["id"]
29
+ end
30
+ end
31
+
32
+ describe "when the response is a Task object" do
33
+ it "should include the generated taskId in the Task object" do
34
+ task = create_task!(text: "ID in response test")
35
+ task["id"].should.not.be.nil
36
+ task["id"].length.should.be > 0
37
+ end
38
+ end
39
+
40
+ # --- Client-Provided taskId References ---
41
+
42
+ describe "when a client provides a taskId that does not correspond to an existing task" do
43
+ it "should return a TaskNotFoundError" do
44
+ body = build_send_message_request(text: "Bad task ref")
45
+ body["message"]["taskId"] = "nonexistent-#{SecureRandom.uuid}"
46
+ response = http_post("/message:send", body)
47
+
48
+ if response.code.to_i >= 400
49
+ true.should.equal true
50
+ else
51
+ data = parse_json(response)
52
+ data.key?("error").should.equal true
53
+ end
54
+ end
55
+ end
56
+
57
+ # --- TaskId as opaque string ---
58
+
59
+ describe "when examining taskId format" do
60
+ it "should treat taskId as an opaque string (no client assumptions about format)" do
61
+ task = create_task!(text: "Opaque ID test")
62
+ # The ID exists and is a non-empty string -- that's all clients should assume
63
+ task["id"].should.be.kind_of String
64
+ task["id"].length.should.be > 0
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,70 @@
1
+ require "a2a_test_framework/test_helper"
2
+ require "time"
3
+
4
+ # Cross-cutting: Timestamp conventions apply to all REST endpoints returning timestamps
5
+
6
+ describe "Timestamp Conventions (REST)" do
7
+ # --- Format Requirements ---
8
+
9
+ describe "when the server returns a response containing timestamp fields" do
10
+ it "should represent timestamps as ISO 8601 formatted strings" do
11
+ task = create_task!(text: "Timestamp format test")
12
+ response = http_get("/tasks/#{task["id"]}")
13
+ data = parse_json(response)
14
+
15
+ timestamp = data["status"]["timestamp"]
16
+ timestamp.should.not.be.nil
17
+ # ISO 8601 basic pattern: YYYY-MM-DD followed by T
18
+ timestamp.should.match(/\d{4}-\d{2}-\d{2}T/)
19
+ end
20
+
21
+ it "should use UTC timezone denoted by Z suffix" do
22
+ task = create_task!(text: "UTC test")
23
+ response = http_get("/tasks/#{task["id"]}")
24
+ data = parse_json(response)
25
+
26
+ timestamp = data["status"]["timestamp"]
27
+ timestamp.should.match(/Z\z/)
28
+ end
29
+
30
+ it "should be parseable as a valid datetime" do
31
+ task = create_task!(text: "Parseable test")
32
+ response = http_get("/tasks/#{task["id"]}")
33
+ data = parse_json(response)
34
+
35
+ timestamp = data["status"]["timestamp"]
36
+ # Should not raise
37
+ parsed = Time.parse(timestamp)
38
+ parsed.should.be.kind_of Time
39
+ end
40
+ end
41
+
42
+ # --- Full pattern validation ---
43
+
44
+ describe "when validating timestamp format" do
45
+ it "should match ISO 8601 pattern with milliseconds" do
46
+ task = create_task!(text: "Pattern test")
47
+ response = http_get("/tasks/#{task["id"]}")
48
+ data = parse_json(response)
49
+
50
+ timestamp = data["status"]["timestamp"]
51
+ # Allow both with and without milliseconds
52
+ valid_pattern = /\A\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?Z\z/
53
+ timestamp.should.match(valid_pattern)
54
+ end
55
+ end
56
+
57
+ # --- Timezone Restrictions ---
58
+
59
+ describe "when validating timezone in timestamps" do
60
+ it "should not include timezone offsets other than Z" do
61
+ task = create_task!(text: "No offset test")
62
+ response = http_get("/tasks/#{task["id"]}")
63
+ data = parse_json(response)
64
+
65
+ timestamp = data["status"]["timestamp"]
66
+ # Should not have +HH:MM or -HH:MM offsets
67
+ timestamp.should.not.match(/[+-]\d{2}:\d{2}\z/)
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,46 @@
1
+ require "a2a_test_framework/test_helper"
2
+
3
+ # NOTE: All tests commented out -- Reference server does not implement version negotiation
4
+
5
+ # require "a2a_test_framework/test_helper"
6
+
7
+ # # NOTE: All tests commented out -- Reference server does not implement version negotiation
8
+
9
+ # # describe "Versioning - Server Responsibilities (REST)" do
10
+ # # describe "when a client sends a request with A2A-Version for a supported version" do
11
+ # # it "should process the request using the semantics of the requested version" do
12
+ # # end
13
+ # # end
14
+ # #
15
+ # # describe "when a client requests an older supported version" do
16
+ # # it "should process the request using the older version semantics" do
17
+ # # end
18
+ # # end
19
+ # #
20
+ # # describe "when a client requests an unsupported version" do
21
+ # # it "should return a VersionNotSupportedError" do
22
+ # # end
23
+ # # end
24
+ # #
25
+ # # describe "when a client sends an empty A2A-Version value" do
26
+ # # it "should interpret the empty value as version 0.3" do
27
+ # # end
28
+ # # end
29
+ # #
30
+ # # describe "when a client sends a request without an A2A-Version header" do
31
+ # # it "should interpret the missing header as version 0.3" do
32
+ # # end
33
+ # # end
34
+ # # end
35
+ # #
36
+ # # describe "Versioning - Client Responsibilities (REST)" do
37
+ # # describe "when a client sends any request to an A2A server" do
38
+ # # it "should include the A2A-Version header" do
39
+ # # end
40
+ # # end
41
+ # #
42
+ # # describe "when A2A-Version is provided as a query parameter" do
43
+ # # it "should accept it as equivalent to the A2A-Version header" do
44
+ # # end
45
+ # # end
46
+ # # end
@@ -0,0 +1,44 @@
1
+ require "a2a_test_framework/test_helper"
2
+
3
+ # Cross-cutting: Protocol versioning applies to all REST endpoints
4
+ # Version is communicated via A2A-Version header.
5
+
6
+ describe "Protocol Versioning (REST)" do
7
+ # NOTE: Version negotiation is not fully implemented in the reference server.
8
+ # These tests verify basic version-related behavior.
9
+
10
+ # --- Version Format ---
11
+ # NOTE: Commented out -- reference server may not validate version header
12
+
13
+ # describe "when a client sends a request with A2A-Version header" do
14
+ # it "should recognize Major.Minor format as valid" do
15
+ # end
16
+ # end
17
+
18
+ # describe "when the server returns version information" do
19
+ # it "should not include patch version numbers" do
20
+ # end
21
+ # end
22
+
23
+ # describe "when performing version negotiation" do
24
+ # it "should not consider patch version differences" do
25
+ # end
26
+ # end
27
+
28
+ # --- Basic Version Behavior ---
29
+
30
+ describe "when the AgentCard declares protocol version" do
31
+ it "should include protocolVersion in supportedInterfaces" do
32
+ response = http_get("/.well-known/agent-card.json")
33
+ data = parse_json(response)
34
+
35
+ data["supportedInterfaces"].each do |iface|
36
+ if iface.key?("protocolVersion")
37
+ iface["protocolVersion"].should.be.kind_of String
38
+ iface["protocolVersion"].should.match(/\d+\.\d+/)
39
+ end
40
+ end
41
+ true.should.equal true
42
+ end
43
+ end
44
+ end
metadata ADDED
@@ -0,0 +1,159 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: a2a-test-framework
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.4.0
5
+ platform: ruby
6
+ authors:
7
+ - Nathan
8
+ bindir: exe
9
+ cert_chain: []
10
+ date: 1980-01-01 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: scampi
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - ">="
17
+ - !ruby/object:Gem::Version
18
+ version: '0'
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - ">="
24
+ - !ruby/object:Gem::Version
25
+ version: '0'
26
+ - !ruby/object:Gem::Dependency
27
+ name: agent2agent
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
40
+ description: A comprehensive test framework for validating A2A protocol server implementations.
41
+ Includes tests for REST and gRPC bindings covering agent discovery, messaging, streaming,
42
+ task management, push notifications, error handling, and more.
43
+ executables:
44
+ - a2a-test
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - a2a.json
49
+ - a2a.proto
50
+ - endpoints/grpc/cancel_task.json
51
+ - endpoints/grpc/create_task_push_notification_config.json
52
+ - endpoints/grpc/delete_task_push_notification_config.json
53
+ - endpoints/grpc/get_extended_agent_card.json
54
+ - endpoints/grpc/get_task.json
55
+ - endpoints/grpc/get_task_push_notification_config.json
56
+ - endpoints/grpc/list_task_push_notification_configs.json
57
+ - endpoints/grpc/list_tasks.json
58
+ - endpoints/grpc/send_message.json
59
+ - endpoints/grpc/send_streaming_message.json
60
+ - endpoints/grpc/subscribe_to_task.json
61
+ - endpoints/rest/cancel_task.json
62
+ - endpoints/rest/create_task_push_notification_config.json
63
+ - endpoints/rest/delete_task_push_notification_config.json
64
+ - endpoints/rest/get_extended_agent_card.json
65
+ - endpoints/rest/get_task.json
66
+ - endpoints/rest/get_task_push_notification_config.json
67
+ - endpoints/rest/list_task_push_notification_configs.json
68
+ - endpoints/rest/list_tasks.json
69
+ - endpoints/rest/send_message.json
70
+ - endpoints/rest/send_streaming_message.json
71
+ - endpoints/rest/subscribe_to_task.json
72
+ - exe/a2a-test
73
+ - lib/a2a_test_framework.rb
74
+ - lib/a2a_test_framework/cli.rb
75
+ - lib/a2a_test_framework/sse_client.rb
76
+ - lib/a2a_test_framework/test_helper.rb
77
+ - lib/a2a_test_framework/version.rb
78
+ - tests/grpc/cancel_task_test.rb
79
+ - tests/grpc/create_task_push_notification_config_test.rb
80
+ - tests/grpc/delete_task_push_notification_config_test.rb
81
+ - tests/grpc/error_code_mappings_test.rb
82
+ - tests/grpc/error_handling_test.rb
83
+ - tests/grpc/get_extended_agent_card_test.rb
84
+ - tests/grpc/get_task_push_notification_config_test.rb
85
+ - tests/grpc/get_task_test.rb
86
+ - tests/grpc/grpc_binding_test.rb
87
+ - tests/grpc/list_task_push_notification_configs_test.rb
88
+ - tests/grpc/list_tasks_test.rb
89
+ - tests/grpc/protocol_data_model_test.rb
90
+ - tests/grpc/send_message_test.rb
91
+ - tests/grpc/send_streaming_message_test.rb
92
+ - tests/grpc/streaming_event_delivery_test.rb
93
+ - tests/grpc/subscribe_to_task_test.rb
94
+ - tests/grpc/versioning_test.rb
95
+ - tests/rest/agent_card_caching_test.rb
96
+ - tests/rest/agent_card_signing_test.rb
97
+ - tests/rest/agent_discovery_test.rb
98
+ - tests/rest/authentication_authorization_test.rb
99
+ - tests/rest/cancel_task_test.rb
100
+ - tests/rest/capability_validation_test.rb
101
+ - tests/rest/context_identifier_semantics_test.rb
102
+ - tests/rest/create_task_push_notification_config_test.rb
103
+ - tests/rest/custom_binding_test.rb
104
+ - tests/rest/delete_task_push_notification_config_test.rb
105
+ - tests/rest/error_code_mappings_test.rb
106
+ - tests/rest/error_handling_test.rb
107
+ - tests/rest/extension_versioning_test.rb
108
+ - tests/rest/field_presence_optionality_test.rb
109
+ - tests/rest/functional_equivalence_test.rb
110
+ - tests/rest/get_extended_agent_card_test.rb
111
+ - tests/rest/get_task_push_notification_config_test.rb
112
+ - tests/rest/get_task_test.rb
113
+ - tests/rest/history_length_semantics_test.rb
114
+ - tests/rest/http_rest_binding_test.rb
115
+ - tests/rest/iana_registrations_test.rb
116
+ - tests/rest/idempotency_test.rb
117
+ - tests/rest/in_task_authorization_test.rb
118
+ - tests/rest/json_field_naming_test.rb
119
+ - tests/rest/json_rpc_binding_test.rb
120
+ - tests/rest/list_task_push_notification_configs_test.rb
121
+ - tests/rest/list_tasks_test.rb
122
+ - tests/rest/messages_and_artifacts_test.rb
123
+ - tests/rest/multi_turn_conversation_test.rb
124
+ - tests/rest/protocol_data_model_test.rb
125
+ - tests/rest/protocol_security_test.rb
126
+ - tests/rest/protocol_selection_negotiation_test.rb
127
+ - tests/rest/push_notification_delivery_test.rb
128
+ - tests/rest/security_considerations_test.rb
129
+ - tests/rest/send_message_test.rb
130
+ - tests/rest/send_streaming_message_test.rb
131
+ - tests/rest/service_parameters_test.rb
132
+ - tests/rest/streaming_event_delivery_test.rb
133
+ - tests/rest/subscribe_to_task_test.rb
134
+ - tests/rest/task_identifier_semantics_test.rb
135
+ - tests/rest/timestamps_test.rb
136
+ - tests/rest/versioning_responsibilities_test.rb
137
+ - tests/rest/versioning_test.rb
138
+ homepage: https://github.com/a2aproject/a2a-test-framework
139
+ licenses:
140
+ - Apache-2.0
141
+ metadata: {}
142
+ rdoc_options: []
143
+ require_paths:
144
+ - lib
145
+ required_ruby_version: !ruby/object:Gem::Requirement
146
+ requirements:
147
+ - - ">="
148
+ - !ruby/object:Gem::Version
149
+ version: '3.1'
150
+ required_rubygems_version: !ruby/object:Gem::Requirement
151
+ requirements:
152
+ - - ">="
153
+ - !ruby/object:Gem::Version
154
+ version: '0'
155
+ requirements: []
156
+ rubygems_version: 3.7.2
157
+ specification_version: 4
158
+ summary: Conformance test suite for A2A (Agent-to-Agent) protocol implementations
159
+ test_files: []