1use super::task::TaskDefinitionFields;
2use crate::models::authentication::*;
3use crate::models::resource::*;
4use serde::{Deserialize, Serialize};
5use serde_json::Value;
6use std::collections::HashMap;
7
8fn default_http_output() -> Option<String> {
9 Some("content".to_string())
10}
11
12string_constants! {
13 CallType {
15 ASYNCAPI => "asyncapi",
16 GRPC => "grpc",
17 HTTP => "http",
18 OPENAPI => "openapi",
19 A2A => "a2a",
20 MCP => "mcp",
21 }
22}
23
24string_constants! {
25 AsyncApiProtocol {
27 AMQP => "amqp",
28 AMQP1 => "amqp1",
29 ANYPOINTMQ => "anypointmq",
30 GOOGLE_PUBSUB => "googlepubsub",
31 HTTP => "http",
32 IBMMQ => "ibmmq",
33 JMS => "jms",
34 KAFKA => "kafka",
35 MERCURE => "mercure",
36 MQTT => "mqtt",
37 MQTT5 => "mqtt5",
38 NATS => "nats",
39 PULSAR => "pulsar",
40 REDIS => "redis",
41 SNS => "sns",
42 SOLACE => "solace",
43 SQS => "sqs",
44 STOMP => "stomp",
45 WS => "ws",
46 }
47}
48
49string_constants! {
50 A2AMethod {
52 MESSAGE_SEND => "message/send",
53 MESSAGE_STREAM => "message/stream",
54 TASKS_GET => "tasks/get",
55 TASKS_LIST => "tasks/list",
56 TASKS_CANCEL => "tasks/cancel",
57 TASKS_RESUBSCRIBE => "tasks/resubscribe",
58 TASKS_PUSH_NOTIFICATION_CONFIG_SET => "tasks/pushNotificationConfig/set",
59 TASKS_PUSH_NOTIFICATION_CONFIG_GET => "tasks/pushNotificationConfig/get",
60 TASKS_PUSH_NOTIFICATION_CONFIG_LIST => "tasks/pushNotificationConfig/list",
61 TASKS_PUSH_NOTIFICATION_CONFIG_DELETE => "tasks/pushNotificationConfig/delete",
62 AGENT_GET_AUTHENTICATED_EXTENDED_CARD => "agent/getAuthenticatedExtendedCard",
63 }
64}
65
66#[derive(Debug, Clone, PartialEq, Serialize)]
68#[serde(untagged)]
69#[allow(clippy::large_enum_variant)]
70pub enum CallTaskDefinition {
71 AsyncAPI(CallAsyncAPIDefinition),
73 GRPC(Box<CallGRPCDefinition>),
75 HTTP(CallHTTPDefinition),
77 OpenAPI(CallOpenAPIDefinition),
79 A2A(CallA2ADefinition),
81 MCP(CallMCPDefinition),
83 Function(CallFunctionDefinition),
85}
86
87impl CallTaskDefinition {
88 pub fn common_fields(&self) -> &super::task::TaskDefinitionFields {
90 match self {
91 CallTaskDefinition::HTTP(t) => &t.common,
92 CallTaskDefinition::GRPC(t) => &t.common,
93 CallTaskDefinition::OpenAPI(t) => &t.common,
94 CallTaskDefinition::AsyncAPI(t) => &t.common,
95 CallTaskDefinition::A2A(t) => &t.common,
96 CallTaskDefinition::MCP(t) => &t.common,
97 CallTaskDefinition::Function(t) => &t.common,
98 }
99 }
100
101 pub fn call_type_name(&self) -> &'static str {
104 match self {
105 CallTaskDefinition::HTTP(_) => "http",
106 CallTaskDefinition::GRPC(_) => "grpc",
107 CallTaskDefinition::OpenAPI(_) => "openapi",
108 CallTaskDefinition::AsyncAPI(_) => "asyncapi",
109 CallTaskDefinition::A2A(_) => "a2a",
110 CallTaskDefinition::MCP(_) => "mcp",
111 CallTaskDefinition::Function(_) => "function",
112 }
113 }
114}
115
116impl<'de> serde::Deserialize<'de> for CallTaskDefinition {
117 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
118 where
119 D: serde::Deserializer<'de>,
120 {
121 let value = Value::deserialize(deserializer)?;
122
123 let call_value = value.get("call").and_then(|v| v.as_str()).unwrap_or("");
124
125 macro_rules! try_call {
126 ($variant:ident, $ty:ty) => {
127 <$ty>::deserialize(value)
128 .map(CallTaskDefinition::$variant)
129 .map_err(serde::de::Error::custom)
130 };
131 }
132 macro_rules! try_call_boxed {
133 ($variant:ident, $ty:ty) => {
134 <$ty>::deserialize(value)
135 .map(|v| CallTaskDefinition::$variant(Box::new(v)))
136 .map_err(serde::de::Error::custom)
137 };
138 }
139
140 match call_value {
141 "asyncapi" => try_call!(AsyncAPI, CallAsyncAPIDefinition),
142 "grpc" => try_call_boxed!(GRPC, CallGRPCDefinition),
143 "http" => try_call!(HTTP, CallHTTPDefinition),
144 "openapi" => try_call!(OpenAPI, CallOpenAPIDefinition),
145 "a2a" => try_call!(A2A, CallA2ADefinition),
146 "mcp" => try_call!(MCP, CallMCPDefinition),
147 _ => try_call!(Function, CallFunctionDefinition),
148 }
149 }
150}
151
152#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize)]
154pub struct HTTPArguments {
155 pub method: String,
157
158 pub endpoint: super::resource::OneOfEndpointDefinitionOrUri,
160
161 #[serde(skip_serializing_if = "Option::is_none")]
163 pub headers: Option<OneOfHeadersOrExpression>,
164
165 #[serde(skip_serializing_if = "Option::is_none")]
167 pub body: Option<Value>,
168
169 #[serde(skip_serializing_if = "Option::is_none")]
171 pub query: Option<OneOfQueryOrExpression>,
172
173 #[serde(
175 default = "default_http_output",
176 skip_serializing_if = "Option::is_none"
177 )]
178 pub output: Option<String>,
179
180 #[serde(skip_serializing_if = "Option::is_none")]
182 pub redirect: Option<bool>,
183}
184
185#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
187#[serde(untagged)]
188pub enum StringMapOrExpression {
189 Map(HashMap<String, String>),
191 Expression(String),
193}
194
195impl Default for StringMapOrExpression {
196 fn default() -> Self {
197 StringMapOrExpression::Map(HashMap::new())
198 }
199}
200
201pub type OneOfHeadersOrExpression = StringMapOrExpression;
203
204pub type OneOfQueryOrExpression = StringMapOrExpression;
206
207macro_rules! define_call_definition {
209 ($( #[$meta:meta] )* $name:ident, $with_ty:ty) => {
210 $( #[$meta] )*
211 #[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize)]
212 pub struct $name {
213 pub call: String,
215
216 pub with: $with_ty,
218
219 #[serde(flatten)]
221 pub common: TaskDefinitionFields,
222 }
223 };
224}
225
226define_call_definition!(
227 CallHTTPDefinition, HTTPArguments
229);
230
231#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize)]
233pub struct GRPCServiceDefinition {
234 pub name: String,
236
237 pub host: String,
239
240 #[serde(skip_serializing_if = "Option::is_none")]
242 pub port: Option<u16>,
243
244 #[serde(skip_serializing_if = "Option::is_none")]
246 pub authentication: Option<ReferenceableAuthenticationPolicy>,
247}
248
249#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize)]
251pub struct GRPCArguments {
252 pub proto: ExternalResourceDefinition,
254
255 pub service: GRPCServiceDefinition,
257
258 pub method: String,
260
261 #[serde(skip_serializing_if = "Option::is_none")]
263 pub arguments: Option<HashMap<String, Value>>,
264
265 #[serde(skip_serializing_if = "Option::is_none")]
267 pub authentication: Option<ReferenceableAuthenticationPolicy>,
268}
269
270define_call_definition!(
271 CallGRPCDefinition, GRPCArguments
273);
274
275#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize)]
277pub struct OpenAPIArguments {
278 pub document: ExternalResourceDefinition,
280
281 #[serde(rename = "operationId")]
283 pub operation_id: String,
284
285 #[serde(skip_serializing_if = "Option::is_none")]
287 pub parameters: Option<HashMap<String, Value>>,
288
289 #[serde(skip_serializing_if = "Option::is_none")]
291 pub authentication: Option<ReferenceableAuthenticationPolicy>,
292
293 #[serde(
295 default = "default_http_output",
296 skip_serializing_if = "Option::is_none"
297 )]
298 pub output: Option<String>,
299
300 #[serde(skip_serializing_if = "Option::is_none")]
302 pub redirect: Option<bool>,
303}
304
305define_call_definition!(
306 CallOpenAPIDefinition, OpenAPIArguments
308);
309
310#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize)]
312pub struct AsyncApiServerDefinition {
313 pub name: String,
315
316 #[serde(skip_serializing_if = "Option::is_none")]
318 pub variables: Option<HashMap<String, Value>>,
319}
320
321#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize)]
323pub struct AsyncApiOutboundMessageDefinition {
324 #[serde(skip_serializing_if = "Option::is_none")]
326 pub payload: Option<Value>,
327
328 #[serde(skip_serializing_if = "Option::is_none")]
330 pub headers: Option<Value>,
331}
332
333#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize)]
335pub struct AsyncApiInboundMessageDefinition {
336 #[serde(skip_serializing_if = "Option::is_none")]
338 pub payload: Option<Value>,
339
340 #[serde(skip_serializing_if = "Option::is_none")]
342 pub headers: Option<Value>,
343
344 #[serde(rename = "correlationId", skip_serializing_if = "Option::is_none")]
346 pub correlation_id: Option<String>,
347}
348
349#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
351#[serde(untagged)]
352pub enum AsyncApiMessageConsumptionPolicy {
353 Amount {
355 amount: u32,
357 },
358 For {
360 #[serde(rename = "for")]
362 for_: super::duration::OneOfDurationOrIso8601Expression,
363 },
364 While {
366 #[serde(rename = "while")]
368 while_: String,
369 },
370 Until {
372 until: String,
374 },
375}
376
377impl Default for AsyncApiMessageConsumptionPolicy {
378 fn default() -> Self {
379 AsyncApiMessageConsumptionPolicy::Amount { amount: 1 }
380 }
381}
382
383#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize)]
385pub struct AsyncApiSubscriptionDefinition {
386 #[serde(skip_serializing_if = "Option::is_none")]
388 pub filter: Option<String>,
389
390 pub consume: AsyncApiMessageConsumptionPolicy,
392
393 #[serde(skip_serializing_if = "Option::is_none")]
395 pub foreach: Option<super::task::SubscriptionIteratorDefinition>,
396}
397
398#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize)]
400pub struct AsyncApiArguments {
401 pub document: ExternalResourceDefinition,
403
404 #[serde(skip_serializing_if = "Option::is_none")]
406 pub channel: Option<String>,
407
408 #[serde(skip_serializing_if = "Option::is_none")]
410 pub operation: Option<String>,
411
412 #[serde(skip_serializing_if = "Option::is_none")]
414 pub server: Option<AsyncApiServerDefinition>,
415
416 #[serde(skip_serializing_if = "Option::is_none")]
418 pub protocol: Option<String>,
419
420 #[serde(skip_serializing_if = "Option::is_none")]
422 pub message: Option<AsyncApiOutboundMessageDefinition>,
423
424 #[serde(skip_serializing_if = "Option::is_none")]
426 pub subscription: Option<AsyncApiSubscriptionDefinition>,
427
428 #[serde(skip_serializing_if = "Option::is_none")]
430 pub authentication: Option<ReferenceableAuthenticationPolicy>,
431}
432
433define_call_definition!(
434 CallAsyncAPIDefinition, AsyncApiArguments
436);
437
438#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
440#[serde(untagged)]
441pub enum OneOfA2AParametersOrExpression {
442 Map(HashMap<String, Value>),
444 Expression(String),
446}
447
448impl Default for OneOfA2AParametersOrExpression {
449 fn default() -> Self {
450 OneOfA2AParametersOrExpression::Map(HashMap::new())
451 }
452}
453
454#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize)]
456pub struct A2AArguments {
457 #[serde(rename = "agentCard", skip_serializing_if = "Option::is_none")]
459 pub agent_card: Option<ExternalResourceDefinition>,
460
461 #[serde(skip_serializing_if = "Option::is_none")]
463 pub server: Option<super::resource::OneOfEndpointDefinitionOrUri>,
464
465 pub method: String,
467
468 #[serde(skip_serializing_if = "Option::is_none")]
470 pub parameters: Option<OneOfA2AParametersOrExpression>,
471}
472
473define_call_definition!(
474 CallA2ADefinition, A2AArguments
476);
477
478string_constants! {
481 McpMethod {
483 TOOLS_LIST => "tools/list",
484 TOOLS_CALL => "tools/call",
485 PROMPTS_LIST => "prompts/list",
486 PROMPTS_GET => "prompts/get",
487 RESOURCES_LIST => "resources/list",
488 RESOURCES_READ => "resources/read",
489 RESOURCES_TEMPLATES_LIST => "resources/templates/list",
490 }
491}
492
493#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
495#[serde(untagged)]
496pub enum OneOfMcpMethodParametersOrExpression {
497 Map(HashMap<String, Value>),
499 Expression(String),
501}
502
503impl Default for OneOfMcpMethodParametersOrExpression {
504 fn default() -> Self {
505 OneOfMcpMethodParametersOrExpression::Map(HashMap::new())
506 }
507}
508
509#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize)]
511pub struct McpHttpTransport {
512 pub endpoint: OneOfEndpointDefinitionOrUri,
514
515 #[serde(skip_serializing_if = "Option::is_none")]
517 pub headers: Option<HashMap<String, String>>,
518}
519
520#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize)]
522pub struct McpStdioTransport {
523 pub command: String,
525
526 #[serde(skip_serializing_if = "Option::is_none")]
528 pub arguments: Option<Vec<String>>,
529
530 #[serde(skip_serializing_if = "Option::is_none")]
532 pub environment: Option<HashMap<String, String>>,
533}
534
535#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize)]
537pub struct McpCallTransport {
538 #[serde(skip_serializing_if = "Option::is_none")]
540 pub http: Option<McpHttpTransport>,
541
542 #[serde(skip_serializing_if = "Option::is_none")]
544 pub stdio: Option<McpStdioTransport>,
545
546 #[serde(skip_serializing_if = "Option::is_none")]
548 pub options: Option<HashMap<String, String>>,
549}
550
551#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize)]
553pub struct McpClient {
554 pub name: String,
556
557 #[serde(skip_serializing_if = "Option::is_none")]
559 pub version: Option<String>,
560
561 #[serde(skip_serializing_if = "Option::is_none")]
563 pub description: Option<String>,
564}
565
566#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize)]
568pub struct MCPArguments {
569 #[serde(
571 rename = "protocolVersion",
572 default = "default_mcp_protocol_version",
573 skip_serializing_if = "Option::is_none"
574 )]
575 pub protocol_version: Option<String>,
576
577 pub method: String,
579
580 #[serde(skip_serializing_if = "Option::is_none")]
582 pub parameters: Option<OneOfMcpMethodParametersOrExpression>,
583
584 #[serde(skip_serializing_if = "Option::is_none")]
586 pub timeout: Option<crate::models::duration::OneOfDurationOrIso8601Expression>,
587
588 pub transport: McpCallTransport,
590
591 #[serde(skip_serializing_if = "Option::is_none")]
593 pub client: Option<McpClient>,
594}
595
596fn default_mcp_protocol_version() -> Option<String> {
597 Some("2025-06-18".to_string())
598}
599
600define_call_definition!(
601 CallMCPDefinition, MCPArguments
603);
604
605#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize)]
607pub struct CallFunctionDefinition {
608 pub call: String,
610
611 #[serde(skip_serializing_if = "Option::is_none")]
613 pub with: Option<HashMap<String, Value>>,
614
615 #[serde(flatten)]
617 pub common: TaskDefinitionFields,
618}
619
620#[cfg(test)]
621mod tests {
622 use super::*;
623
624 #[test]
625 fn test_call_http_deserialize() {
626 let json = r#"{
627 "call": "http",
628 "with": {
629 "method": "GET",
630 "endpoint": "http://example.com/api"
631 }
632 }"#;
633 let http: CallHTTPDefinition = serde_json::from_str(json).unwrap();
634 assert_eq!(http.call, "http");
635 assert_eq!(http.with.method, "GET");
636 match &http.with.endpoint {
637 OneOfEndpointDefinitionOrUri::Uri(uri) => assert_eq!(uri, "http://example.com/api"),
638 _ => panic!("Expected Uri variant"),
639 }
640 }
641
642 #[test]
643 fn test_call_http_with_headers_and_query() {
644 let json = r#"{
645 "call": "http",
646 "with": {
647 "method": "POST",
648 "endpoint": "http://example.com/api",
649 "headers": {"Authorization": "Bearer token"},
650 "query": {"page": "1"},
651 "output": "response",
652 "redirect": true
653 }
654 }"#;
655 let http: CallHTTPDefinition = serde_json::from_str(json).unwrap();
656 assert_eq!(http.with.method, "POST");
657 assert!(http.with.headers.is_some());
658 assert!(http.with.query.is_some());
659 assert_eq!(http.with.output, Some("response".to_string()));
660 assert_eq!(http.with.redirect, Some(true));
661 }
662
663 #[test]
664 fn test_call_http_roundtrip() {
665 let json = r#"{
666 "call": "http",
667 "with": {
668 "method": "GET",
669 "endpoint": "http://example.com/api"
670 }
671 }"#;
672 let http: CallHTTPDefinition = serde_json::from_str(json).unwrap();
673 let serialized = serde_json::to_string(&http).unwrap();
674 let deserialized: CallHTTPDefinition = serde_json::from_str(&serialized).unwrap();
675 assert_eq!(http, deserialized);
676 }
677
678 #[test]
679 fn test_call_http_with_endpoint_config() {
680 let json = r#"{
681 "call": "http",
682 "with": {
683 "method": "GET",
684 "endpoint": {
685 "uri": "http://example.com/{id}",
686 "authentication": {
687 "basic": {"username": "admin", "password": "secret"}
688 }
689 }
690 }
691 }"#;
692 let http: CallHTTPDefinition = serde_json::from_str(json).unwrap();
693 match &http.with.endpoint {
694 OneOfEndpointDefinitionOrUri::Endpoint(ep) => {
695 assert_eq!(ep.uri, "http://example.com/{id}");
696 assert!(ep.authentication.is_some());
697 }
698 _ => panic!("Expected Endpoint variant"),
699 }
700 }
701
702 #[test]
703 fn test_call_grpc_deserialize() {
704 let json = r#"{
705 "call": "grpc",
706 "with": {
707 "proto": {
708 "name": "MyProto",
709 "endpoint": "http://example.com/proto"
710 },
711 "service": {
712 "name": "UserService",
713 "host": "example.com",
714 "port": 50051
715 },
716 "method": "GetUser",
717 "arguments": {"userId": "12345"}
718 }
719 }"#;
720 let grpc: CallGRPCDefinition = serde_json::from_str(json).unwrap();
721 assert_eq!(grpc.call, "grpc");
722 assert_eq!(grpc.with.proto.name, Some("MyProto".to_string()));
723 assert_eq!(grpc.with.service.name, "UserService");
724 assert_eq!(grpc.with.service.host, "example.com");
725 assert_eq!(grpc.with.service.port, Some(50051));
726 assert_eq!(grpc.with.method, "GetUser");
727 }
728
729 #[test]
730 fn test_call_grpc_roundtrip() {
731 let json = r#"{
732 "call": "grpc",
733 "with": {
734 "proto": {
735 "name": "MyProto",
736 "endpoint": "http://example.com/proto"
737 },
738 "service": {
739 "name": "UserService",
740 "host": "example.com",
741 "port": 50051
742 },
743 "method": "GetUser"
744 }
745 }"#;
746 let grpc: CallGRPCDefinition = serde_json::from_str(json).unwrap();
747 let serialized = serde_json::to_string(&grpc).unwrap();
748 let deserialized: CallGRPCDefinition = serde_json::from_str(&serialized).unwrap();
749 assert_eq!(grpc, deserialized);
750 }
751
752 #[test]
753 fn test_call_openapi_deserialize() {
754 let json = r#"{
755 "call": "openapi",
756 "with": {
757 "document": {
758 "name": "MyOpenAPIDoc",
759 "endpoint": "http://example.com/openapi.json"
760 },
761 "operationId": "getUsers",
762 "parameters": {"param1": "value1"},
763 "authentication": {"use": "my-auth"},
764 "output": "content",
765 "redirect": true
766 }
767 }"#;
768 let openapi: CallOpenAPIDefinition = serde_json::from_str(json).unwrap();
769 assert_eq!(openapi.call, "openapi");
770 assert_eq!(openapi.with.operation_id, "getUsers");
771 assert!(openapi.with.parameters.is_some());
772 assert!(openapi.with.authentication.is_some());
773 assert_eq!(openapi.with.output, Some("content".to_string()));
774 assert_eq!(openapi.with.redirect, Some(true));
775 }
776
777 #[test]
778 fn test_call_openapi_roundtrip() {
779 let json = r#"{
780 "call": "openapi",
781 "with": {
782 "document": {
783 "name": "MyOpenAPIDoc",
784 "endpoint": "http://example.com/openapi.json"
785 },
786 "operationId": "getUsers"
787 }
788 }"#;
789 let openapi: CallOpenAPIDefinition = serde_json::from_str(json).unwrap();
790 let serialized = serde_json::to_string(&openapi).unwrap();
791 let deserialized: CallOpenAPIDefinition = serde_json::from_str(&serialized).unwrap();
792 assert_eq!(openapi, deserialized);
793 }
794
795 #[test]
796 fn test_call_asyncapi_deserialize() {
797 let json = r#"{
798 "call": "asyncapi",
799 "with": {
800 "document": {
801 "name": "MyAsyncAPIDoc",
802 "endpoint": "http://example.com/asyncapi.json"
803 },
804 "operation": "user.signup",
805 "server": {"name": "default-server"},
806 "protocol": "http",
807 "message": {
808 "payload": {"userId": "12345"}
809 },
810 "authentication": {"use": "asyncapi-auth"}
811 }
812 }"#;
813 let asyncapi: CallAsyncAPIDefinition = serde_json::from_str(json).unwrap();
814 assert_eq!(asyncapi.call, "asyncapi");
815 assert_eq!(asyncapi.with.operation, Some("user.signup".to_string()));
816 assert!(asyncapi.with.server.is_some());
817 assert_eq!(asyncapi.with.protocol, Some("http".to_string()));
818 assert!(asyncapi.with.message.is_some());
819 assert!(asyncapi.with.authentication.is_some());
820 }
821
822 #[test]
823 fn test_call_asyncapi_roundtrip() {
824 let json = r#"{
825 "call": "asyncapi",
826 "with": {
827 "document": {
828 "name": "MyAsyncAPIDoc",
829 "endpoint": "http://example.com/asyncapi.json"
830 },
831 "operation": "user.signup",
832 "protocol": "http"
833 }
834 }"#;
835 let asyncapi: CallAsyncAPIDefinition = serde_json::from_str(json).unwrap();
836 let serialized = serde_json::to_string(&asyncapi).unwrap();
837 let deserialized: CallAsyncAPIDefinition = serde_json::from_str(&serialized).unwrap();
838 assert_eq!(asyncapi, deserialized);
839 }
840
841 #[test]
842 fn test_call_function_deserialize() {
843 let json = r#"{
844 "call": "myFunction",
845 "with": {
846 "param1": "value1",
847 "param2": 42
848 }
849 }"#;
850 let func: CallFunctionDefinition = serde_json::from_str(json).unwrap();
851 assert_eq!(func.call, "myFunction");
852 assert!(func.with.is_some());
853 let with = func.with.unwrap();
854 assert_eq!(with.get("param1").unwrap(), "value1");
855 }
856
857 #[test]
858 fn test_call_function_roundtrip() {
859 let json = r#"{
860 "call": "myFunction",
861 "with": {"param1": "value1"}
862 }"#;
863 let func: CallFunctionDefinition = serde_json::from_str(json).unwrap();
864 let serialized = serde_json::to_string(&func).unwrap();
865 let deserialized: CallFunctionDefinition = serde_json::from_str(&serialized).unwrap();
866 assert_eq!(func, deserialized);
867 }
868
869 #[test]
870 fn test_call_a2a_deserialize() {
871 let json = r#"{
872 "call": "a2a",
873 "with": {
874 "method": "message/send",
875 "parameters": {"message": "hello"}
876 }
877 }"#;
878 let a2a: CallA2ADefinition = serde_json::from_str(json).unwrap();
879 assert_eq!(a2a.call, "a2a");
880 assert_eq!(a2a.with.method, "message/send");
881 assert!(a2a.with.parameters.is_some());
882 }
883
884 #[test]
885 fn test_call_task_definition_http() {
886 let json =
887 r#"{"call": "http", "with": {"method": "GET", "endpoint": "http://example.com"}}"#;
888 let def: CallTaskDefinition = serde_json::from_str(json).unwrap();
889 match def {
890 CallTaskDefinition::HTTP(http) => assert_eq!(http.call, "http"),
891 _ => panic!("Expected HTTP variant"),
892 }
893 }
894
895 #[test]
896 fn test_call_task_definition_grpc() {
897 let json = r#"{"call": "grpc", "with": {"proto": {"endpoint": "http://example.com/proto"}, "service": {"name": "Svc", "host": "example.com"}, "method": "Get"}}"#;
898 let def: CallTaskDefinition = serde_json::from_str(json).unwrap();
899 match def {
900 CallTaskDefinition::GRPC(grpc) => assert_eq!(grpc.call, "grpc"),
901 _ => panic!("Expected GRPC variant"),
902 }
903 }
904
905 #[test]
906 fn test_call_task_definition_openapi() {
907 let json = r#"{"call": "openapi", "with": {"document": {"endpoint": "http://example.com/openapi.json"}, "operationId": "op1"}}"#;
908 let def: CallTaskDefinition = serde_json::from_str(json).unwrap();
909 match def {
910 CallTaskDefinition::OpenAPI(openapi) => assert_eq!(openapi.call, "openapi"),
911 _ => panic!("Expected OpenAPI variant"),
912 }
913 }
914
915 #[test]
916 fn test_call_task_definition_function() {
917 let json = r#"{"call": "myFunc", "with": {"key": "val"}}"#;
918 let def: CallTaskDefinition = serde_json::from_str(json).unwrap();
919 match def {
920 CallTaskDefinition::Function(func) => assert_eq!(func.call, "myFunc"),
921 _ => panic!("Expected Function variant"),
922 }
923 }
924
925 #[test]
926 fn test_headers_map_vs_expression() {
927 let map_json = r#"{"Authorization": "Bearer token"}"#;
928 let map: OneOfHeadersOrExpression = serde_json::from_str(map_json).unwrap();
929 assert!(matches!(map, OneOfHeadersOrExpression::Map(_)));
930
931 let expr_json = r#""${ .headers }""#;
932 let expr: OneOfHeadersOrExpression = serde_json::from_str(expr_json).unwrap();
933 assert!(matches!(expr, OneOfHeadersOrExpression::Expression(_)));
934 }
935
936 #[test]
937 fn test_query_map_vs_expression() {
938 let map_json = r#"{"page": "1"}"#;
939 let map: OneOfQueryOrExpression = serde_json::from_str(map_json).unwrap();
940 assert!(matches!(map, OneOfQueryOrExpression::Map(_)));
941
942 let expr_json = r#""${ .queryParams }""#;
943 let expr: OneOfQueryOrExpression = serde_json::from_str(expr_json).unwrap();
944 assert!(matches!(expr, OneOfQueryOrExpression::Expression(_)));
945 }
946
947 #[test]
948 fn test_asyncapi_consumption_policy_amount() {
949 let json = r#"{"amount": 5}"#;
950 let policy: AsyncApiMessageConsumptionPolicy = serde_json::from_str(json).unwrap();
951 match policy {
952 AsyncApiMessageConsumptionPolicy::Amount { amount } => assert_eq!(amount, 5),
953 _ => panic!("Expected Amount variant"),
954 }
955 }
956
957 #[test]
958 fn test_asyncapi_consumption_policy_for() {
959 let json = r#"{"for": "PT30S"}"#;
960 let policy: AsyncApiMessageConsumptionPolicy = serde_json::from_str(json).unwrap();
961 match policy {
962 AsyncApiMessageConsumptionPolicy::For { for_ } => {
963 assert!(matches!(
965 for_,
966 crate::models::duration::OneOfDurationOrIso8601Expression::Iso8601Expression(_)
967 ));
968 }
969 _ => panic!("Expected For variant"),
970 }
971 }
972
973 #[test]
974 fn test_asyncapi_consumption_policy_for_duration() {
975 let json = r#"{"for": {"seconds": 30}}"#;
976 let policy: AsyncApiMessageConsumptionPolicy = serde_json::from_str(json).unwrap();
977 match policy {
978 AsyncApiMessageConsumptionPolicy::For { for_ } => {
979 assert!(matches!(
980 for_,
981 crate::models::duration::OneOfDurationOrIso8601Expression::Duration(_)
982 ));
983 }
984 _ => panic!("Expected For variant"),
985 }
986 }
987
988 #[test]
989 fn test_asyncapi_consumption_policy_while() {
990 let json = r#"{"while": "${ .counter < 10 }"}"#;
991 let policy: AsyncApiMessageConsumptionPolicy = serde_json::from_str(json).unwrap();
992 match policy {
993 AsyncApiMessageConsumptionPolicy::While { while_ } => {
994 assert_eq!(while_, "${ .counter < 10 }");
995 }
996 _ => panic!("Expected While variant"),
997 }
998 }
999
1000 #[test]
1001 fn test_grpc_service_with_authentication() {
1002 let json = r#"{
1003 "name": "UserService",
1004 "host": "example.com",
1005 "port": 50051,
1006 "authentication": {"use": "grpc-auth"}
1007 }"#;
1008 let service: GRPCServiceDefinition = serde_json::from_str(json).unwrap();
1009 assert_eq!(service.name, "UserService");
1010 assert!(service.authentication.is_some());
1011 }
1012
1013 #[test]
1016 fn test_call_http_with_common_fields() {
1017 let json = r#"{
1019 "if": "${condition}",
1020 "input": {"from": {"key": "value"}},
1021 "output": {"as": {"result": "output"}},
1022 "timeout": {"after": "PT10S"},
1023 "then": "continue",
1024 "metadata": {"meta": "data"},
1025 "call": "http",
1026 "with": {
1027 "method": "GET",
1028 "endpoint": "http://example.com",
1029 "headers": {"Authorization": "Bearer token"},
1030 "query": {"q": "search"},
1031 "output": "content",
1032 "redirect": true
1033 }
1034 }"#;
1035 let http: CallHTTPDefinition = serde_json::from_str(json).unwrap();
1036 assert_eq!(http.call, "http");
1037 assert_eq!(http.common.if_, Some("${condition}".to_string()));
1038 assert!(http.common.input.is_some());
1039 assert!(http.common.output.is_some());
1040 assert!(http.common.timeout.is_some());
1041 assert_eq!(http.common.then, Some("continue".to_string()));
1042 assert!(http.common.metadata.is_some());
1043 assert_eq!(http.with.method, "GET");
1044 assert_eq!(http.with.output, Some("content".to_string()));
1045 assert_eq!(http.with.redirect, Some(true));
1046 }
1047
1048 #[test]
1049 fn test_call_http_with_common_fields_roundtrip() {
1050 let json = r#"{
1051 "if": "${condition}",
1052 "input": {"from": {"key": "value"}},
1053 "output": {"as": {"result": "output"}},
1054 "timeout": {"after": "PT10S"},
1055 "then": "continue",
1056 "call": "http",
1057 "with": {
1058 "method": "GET",
1059 "endpoint": "http://example.com"
1060 }
1061 }"#;
1062 let http: CallHTTPDefinition = serde_json::from_str(json).unwrap();
1063 let serialized = serde_json::to_string(&http).unwrap();
1064 let deserialized: CallHTTPDefinition = serde_json::from_str(&serialized).unwrap();
1065 assert_eq!(http, deserialized);
1066 }
1067
1068 #[test]
1069 fn test_call_openapi_with_authentication() {
1070 let json = r#"{
1072 "call": "openapi",
1073 "with": {
1074 "document": {
1075 "name": "MyOpenAPIDoc",
1076 "endpoint": "http://example.com/openapi.json"
1077 },
1078 "operationId": "getUsers",
1079 "parameters": {"param1": "value1", "param2": "value2"},
1080 "authentication": {"use": "my-auth"},
1081 "output": "content",
1082 "redirect": true
1083 }
1084 }"#;
1085 let openapi: CallOpenAPIDefinition = serde_json::from_str(json).unwrap();
1086 assert_eq!(openapi.with.operation_id, "getUsers");
1087 assert!(openapi.with.authentication.is_some());
1088 assert_eq!(openapi.with.output, Some("content".to_string()));
1089 assert_eq!(openapi.with.redirect, Some(true));
1090 }
1091
1092 #[test]
1093 fn test_call_grpc_with_full_arguments() {
1094 let json = r#"{
1096 "call": "grpc",
1097 "with": {
1098 "proto": {
1099 "name": "MyProtoFile",
1100 "endpoint": "http://example.com/protofile"
1101 },
1102 "service": {
1103 "name": "UserService",
1104 "host": "example.com",
1105 "port": 50051
1106 },
1107 "method": "GetUser",
1108 "arguments": {"userId": "12345"}
1109 }
1110 }"#;
1111 let grpc: CallGRPCDefinition = serde_json::from_str(json).unwrap();
1112 assert_eq!(grpc.call, "grpc");
1113 assert_eq!(grpc.with.proto.name, Some("MyProtoFile".to_string()));
1114 assert_eq!(grpc.with.service.name, "UserService");
1115 assert_eq!(grpc.with.service.host, "example.com");
1116 assert_eq!(grpc.with.service.port, Some(50051));
1117 assert_eq!(grpc.with.method, "GetUser");
1118 assert!(grpc.with.arguments.is_some());
1119 }
1120
1121 #[test]
1122 fn test_call_asyncapi_with_subscription() {
1123 let json = r#"{
1124 "call": "asyncapi",
1125 "with": {
1126 "document": {
1127 "name": "MyAsyncAPIDoc",
1128 "endpoint": "http://example.com/asyncapi.json"
1129 },
1130 "operation": "user.signup",
1131 "server": {"name": "default-server"},
1132 "protocol": "http",
1133 "subscription": {
1134 "filter": "${ .type == \"order\" }",
1135 "consume": {"amount": 5}
1136 },
1137 "authentication": {"use": "asyncapi-auth-policy"}
1138 }
1139 }"#;
1140 let asyncapi: CallAsyncAPIDefinition = serde_json::from_str(json).unwrap();
1141 assert_eq!(asyncapi.with.operation, Some("user.signup".to_string()));
1142 assert!(asyncapi.with.subscription.is_some());
1143 let sub = asyncapi.with.subscription.as_ref().unwrap();
1144 assert!(sub.filter.is_some());
1145 match &sub.consume {
1146 AsyncApiMessageConsumptionPolicy::Amount { amount } => assert_eq!(*amount, 5),
1147 _ => panic!("Expected Amount variant"),
1148 }
1149 }
1150
1151 #[test]
1152 fn test_call_asyncapi_with_message_and_subscription() {
1153 let json = r#"{
1155 "call": "asyncapi",
1156 "with": {
1157 "document": {"endpoint": "http://example.com/asyncapi.json"},
1158 "operation": "order.process",
1159 "protocol": "kafka",
1160 "message": {"payload": {"orderId": "123"}},
1161 "subscription": {
1162 "consume": {"while": "${ .status != \"completed\" }"}
1163 }
1164 }
1165 }"#;
1166 let asyncapi: CallAsyncAPIDefinition = serde_json::from_str(json).unwrap();
1167 assert!(asyncapi.with.message.is_some());
1168 assert!(asyncapi.with.subscription.is_some());
1169 let sub = asyncapi.with.subscription.as_ref().unwrap();
1170 match &sub.consume {
1171 AsyncApiMessageConsumptionPolicy::While { while_ } => {
1172 assert_eq!(while_, "${ .status != \"completed\" }");
1173 }
1174 _ => panic!("Expected While variant"),
1175 }
1176 }
1177
1178 #[test]
1179 fn test_call_function_with_common_fields_roundtrip() {
1180 let json = r#"{
1181 "call": "myFunction",
1182 "with": {"param1": "value1", "param2": 42}
1183 }"#;
1184 let func: CallFunctionDefinition = serde_json::from_str(json).unwrap();
1185 let serialized = serde_json::to_string(&func).unwrap();
1186 let deserialized: CallFunctionDefinition = serde_json::from_str(&serialized).unwrap();
1187 assert_eq!(func, deserialized);
1188 }
1189
1190 #[test]
1191 fn test_call_a2a_with_agent_card() {
1192 let json = r#"{
1193 "call": "a2a",
1194 "with": {
1195 "agentCard": {
1196 "name": "my-agent",
1197 "endpoint": "http://example.com/agent-card"
1198 },
1199 "server": "http://example.com/a2a-server",
1200 "method": "tasks/get",
1201 "parameters": {"taskId": "123"}
1202 }
1203 }"#;
1204 let a2a: CallA2ADefinition = serde_json::from_str(json).unwrap();
1205 assert_eq!(a2a.call, "a2a");
1206 assert!(a2a.with.agent_card.is_some());
1207 assert!(a2a.with.server.is_some());
1208 assert_eq!(a2a.with.method, "tasks/get");
1209 assert!(a2a.with.parameters.is_some());
1210 }
1211
1212 #[test]
1213 fn test_call_a2a_roundtrip() {
1214 let json = r#"{
1215 "call": "a2a",
1216 "with": {
1217 "method": "message/send",
1218 "parameters": {"message": "hello"}
1219 }
1220 }"#;
1221 let a2a: CallA2ADefinition = serde_json::from_str(json).unwrap();
1222 let serialized = serde_json::to_string(&a2a).unwrap();
1223 let deserialized: CallA2ADefinition = serde_json::from_str(&serialized).unwrap();
1224 assert_eq!(a2a, deserialized);
1225 }
1226
1227 #[test]
1230 fn test_call_grpc_with_common_fields() {
1231 let json = r#"{
1233 "if": "${condition}",
1234 "input": {"from": {"key": "value"}},
1235 "output": {"as": {"result": "output"}},
1236 "timeout": {"after": "PT10S"},
1237 "then": "continue",
1238 "metadata": {"meta": "data"},
1239 "call": "grpc",
1240 "with": {
1241 "proto": {
1242 "name": "MyProtoFile",
1243 "endpoint": "http://example.com/protofile"
1244 },
1245 "service": {
1246 "name": "UserService",
1247 "host": "example.com",
1248 "port": 50051
1249 },
1250 "method": "GetUser",
1251 "arguments": {"userId": "12345"}
1252 }
1253 }"#;
1254 let grpc: CallGRPCDefinition = serde_json::from_str(json).unwrap();
1255 assert_eq!(grpc.call, "grpc");
1256 assert_eq!(grpc.common.if_, Some("${condition}".to_string()));
1257 assert!(grpc.common.input.is_some());
1258 assert!(grpc.common.output.is_some());
1259 assert!(grpc.common.timeout.is_some());
1260 assert_eq!(grpc.common.then, Some("continue".to_string()));
1261 assert!(grpc.common.metadata.is_some());
1262 assert_eq!(grpc.with.service.name, "UserService");
1263 assert_eq!(grpc.with.method, "GetUser");
1264 }
1265
1266 #[test]
1267 fn test_call_grpc_with_common_fields_roundtrip() {
1268 let json = r#"{
1269 "if": "${condition}",
1270 "output": {"as": {"result": "output"}},
1271 "then": "continue",
1272 "call": "grpc",
1273 "with": {
1274 "proto": {"endpoint": "http://example.com/proto"},
1275 "service": {"name": "Svc", "host": "example.com"},
1276 "method": "Get"
1277 }
1278 }"#;
1279 let grpc: CallGRPCDefinition = serde_json::from_str(json).unwrap();
1280 let serialized = serde_json::to_string(&grpc).unwrap();
1281 let deserialized: CallGRPCDefinition = serde_json::from_str(&serialized).unwrap();
1282 assert_eq!(grpc, deserialized);
1283 }
1284
1285 #[test]
1286 fn test_call_openapi_with_common_fields() {
1287 let json = r#"{
1289 "if": "${condition}",
1290 "input": {"from": {"key": "value"}},
1291 "output": {"as": {"result": "output"}},
1292 "timeout": {"after": "PT10S"},
1293 "then": "continue",
1294 "metadata": {"meta": "data"},
1295 "call": "openapi",
1296 "with": {
1297 "document": {
1298 "name": "MyOpenAPIDoc",
1299 "endpoint": "http://example.com/openapi.json"
1300 },
1301 "operationId": "getUsers",
1302 "parameters": {"param1": "value1"},
1303 "authentication": {"use": "my-auth"},
1304 "output": "content",
1305 "redirect": true
1306 }
1307 }"#;
1308 let openapi: CallOpenAPIDefinition = serde_json::from_str(json).unwrap();
1309 assert_eq!(openapi.call, "openapi");
1310 assert_eq!(openapi.common.if_, Some("${condition}".to_string()));
1311 assert!(openapi.common.input.is_some());
1312 assert!(openapi.common.output.is_some());
1313 assert!(openapi.common.timeout.is_some());
1314 assert_eq!(openapi.common.then, Some("continue".to_string()));
1315 assert!(openapi.common.metadata.is_some());
1316 assert_eq!(openapi.with.operation_id, "getUsers");
1317 assert_eq!(openapi.with.output, Some("content".to_string()));
1318 assert_eq!(openapi.with.redirect, Some(true));
1319 }
1320
1321 #[test]
1322 fn test_call_openapi_with_common_fields_roundtrip() {
1323 let json = r#"{
1324 "if": "${condition}",
1325 "output": {"as": {"result": "output"}},
1326 "then": "continue",
1327 "call": "openapi",
1328 "with": {
1329 "document": {"endpoint": "http://example.com/openapi.json"},
1330 "operationId": "op1"
1331 }
1332 }"#;
1333 let openapi: CallOpenAPIDefinition = serde_json::from_str(json).unwrap();
1334 let serialized = serde_json::to_string(&openapi).unwrap();
1335 let deserialized: CallOpenAPIDefinition = serde_json::from_str(&serialized).unwrap();
1336 assert_eq!(openapi, deserialized);
1337 }
1338
1339 #[test]
1340 fn test_call_asyncapi_with_common_fields() {
1341 let json = r#"{
1343 "if": "${condition}",
1344 "input": {"from": {"key": "value"}},
1345 "output": {"as": {"result": "output"}},
1346 "timeout": {"after": "PT10S"},
1347 "then": "continue",
1348 "metadata": {"meta": "data"},
1349 "call": "asyncapi",
1350 "with": {
1351 "document": {
1352 "name": "MyAsyncAPIDoc",
1353 "endpoint": "http://example.com/asyncapi.json"
1354 },
1355 "operation": "user.signup",
1356 "server": {"name": "default-server"},
1357 "protocol": "http",
1358 "message": {
1359 "payload": {"userId": "12345"}
1360 },
1361 "authentication": {"use": "asyncapi-auth-policy"}
1362 }
1363 }"#;
1364 let asyncapi: CallAsyncAPIDefinition = serde_json::from_str(json).unwrap();
1365 assert_eq!(asyncapi.call, "asyncapi");
1366 assert_eq!(asyncapi.common.if_, Some("${condition}".to_string()));
1367 assert!(asyncapi.common.input.is_some());
1368 assert!(asyncapi.common.output.is_some());
1369 assert!(asyncapi.common.timeout.is_some());
1370 assert_eq!(asyncapi.common.then, Some("continue".to_string()));
1371 assert!(asyncapi.common.metadata.is_some());
1372 assert_eq!(asyncapi.with.operation, Some("user.signup".to_string()));
1373 assert_eq!(asyncapi.with.protocol, Some("http".to_string()));
1374 }
1375
1376 #[test]
1377 fn test_call_asyncapi_with_common_fields_roundtrip() {
1378 let json = r#"{
1379 "if": "${condition}",
1380 "output": {"as": {"result": "output"}},
1381 "then": "continue",
1382 "call": "asyncapi",
1383 "with": {
1384 "document": {"endpoint": "http://example.com/asyncapi.json"},
1385 "operation": "user.signup",
1386 "protocol": "http"
1387 }
1388 }"#;
1389 let asyncapi: CallAsyncAPIDefinition = serde_json::from_str(json).unwrap();
1390 let serialized = serde_json::to_string(&asyncapi).unwrap();
1391 let deserialized: CallAsyncAPIDefinition = serde_json::from_str(&serialized).unwrap();
1392 assert_eq!(asyncapi, deserialized);
1393 }
1394
1395 #[test]
1396 fn test_call_function_with_common_fields() {
1397 let json = r#"{
1399 "if": "${condition}",
1400 "input": {"from": {"key": "value"}},
1401 "output": {"as": {"result": "output"}},
1402 "timeout": {"after": "PT10S"},
1403 "then": "continue",
1404 "metadata": {"meta": "data"},
1405 "call": "myFunction",
1406 "with": {"param1": "value1", "param2": 42}
1407 }"#;
1408 let func: CallFunctionDefinition = serde_json::from_str(json).unwrap();
1409 assert_eq!(func.call, "myFunction");
1410 assert_eq!(func.common.if_, Some("${condition}".to_string()));
1411 assert!(func.common.input.is_some());
1412 assert!(func.common.output.is_some());
1413 assert!(func.common.timeout.is_some());
1414 assert_eq!(func.common.then, Some("continue".to_string()));
1415 assert!(func.common.metadata.is_some());
1416 }
1417
1418 #[test]
1419 fn test_call_a2a_with_common_fields() {
1420 let json = r#"{
1421 "if": "${condition}",
1422 "input": {"from": {"key": "value"}},
1423 "output": {"as": {"result": "output"}},
1424 "timeout": {"after": "PT10S"},
1425 "then": "continue",
1426 "call": "a2a",
1427 "with": {
1428 "method": "message/send",
1429 "parameters": {"message": "hello"}
1430 }
1431 }"#;
1432 let a2a: CallA2ADefinition = serde_json::from_str(json).unwrap();
1433 assert_eq!(a2a.call, "a2a");
1434 assert_eq!(a2a.common.if_, Some("${condition}".to_string()));
1435 assert!(a2a.common.input.is_some());
1436 assert!(a2a.common.output.is_some());
1437 assert!(a2a.common.timeout.is_some());
1438 assert_eq!(a2a.common.then, Some("continue".to_string()));
1439 }
1440
1441 #[test]
1442 fn test_call_http_with_body() {
1443 let json = r#"{
1445 "call": "http",
1446 "with": {
1447 "method": "POST",
1448 "endpoint": "http://example.com/api",
1449 "headers": {"Content-Type": "application/json"},
1450 "body": {"name": "test", "value": 42},
1451 "output": "content"
1452 }
1453 }"#;
1454 let http: CallHTTPDefinition = serde_json::from_str(json).unwrap();
1455 assert_eq!(http.with.method, "POST");
1456 assert!(http.with.body.is_some());
1457 let body = http.with.body.unwrap();
1458 assert_eq!(body["name"], "test");
1459 assert_eq!(body["value"], 42);
1460 }
1461
1462 #[test]
1463 fn test_call_http_headers_expression() {
1464 let json = r#"{
1466 "call": "http",
1467 "with": {
1468 "method": "GET",
1469 "endpoint": "http://example.com",
1470 "headers": "${ .requestHeaders }"
1471 }
1472 }"#;
1473 let http: CallHTTPDefinition = serde_json::from_str(json).unwrap();
1474 match &http.with.headers {
1475 Some(OneOfHeadersOrExpression::Expression(expr)) => {
1476 assert_eq!(expr, "${ .requestHeaders }");
1477 }
1478 _ => panic!("Expected Expression variant for headers"),
1479 }
1480 }
1481
1482 #[test]
1483 fn test_call_http_query_expression() {
1484 let json = r#"{
1486 "call": "http",
1487 "with": {
1488 "method": "GET",
1489 "endpoint": "http://example.com",
1490 "query": "${ .queryParams }"
1491 }
1492 }"#;
1493 let http: CallHTTPDefinition = serde_json::from_str(json).unwrap();
1494 match &http.with.query {
1495 Some(OneOfQueryOrExpression::Expression(expr)) => {
1496 assert_eq!(expr, "${ .queryParams }");
1497 }
1498 _ => panic!("Expected Expression variant for query"),
1499 }
1500 }
1501
1502 #[test]
1503 fn test_call_grpc_service_with_authentication_roundtrip() {
1504 let json = r#"{
1505 "call": "grpc",
1506 "with": {
1507 "proto": {"endpoint": "http://example.com/proto"},
1508 "service": {
1509 "name": "Svc",
1510 "host": "example.com",
1511 "authentication": {"use": "grpc-auth"}
1512 },
1513 "method": "Get"
1514 }
1515 }"#;
1516 let grpc: CallGRPCDefinition = serde_json::from_str(json).unwrap();
1517 let serialized = serde_json::to_string(&grpc).unwrap();
1518 let deserialized: CallGRPCDefinition = serde_json::from_str(&serialized).unwrap();
1519 assert_eq!(grpc, deserialized);
1520 }
1521
1522 #[test]
1523 fn test_call_a2a_with_parameters_expression() {
1524 let json = r#"{
1526 "call": "a2a",
1527 "with": {
1528 "method": "tasks/get",
1529 "parameters": "${ .taskParams }"
1530 }
1531 }"#;
1532 let a2a: CallA2ADefinition = serde_json::from_str(json).unwrap();
1533 match &a2a.with.parameters {
1534 Some(OneOfA2AParametersOrExpression::Expression(expr)) => {
1535 assert_eq!(expr, "${ .taskParams }");
1536 }
1537 _ => panic!("Expected Expression variant for parameters"),
1538 }
1539 }
1540
1541 #[test]
1542 fn test_call_grpc_with_authentication() {
1543 let json = r#"{
1545 "call": "grpc",
1546 "with": {
1547 "proto": {"endpoint": "http://example.com/proto"},
1548 "service": {
1549 "name": "UserService",
1550 "host": "example.com"
1551 },
1552 "method": "GetUser",
1553 "arguments": {"userId": "12345"},
1554 "authentication": {"use": "my-auth"}
1555 }
1556 }"#;
1557 let grpc: CallGRPCDefinition = serde_json::from_str(json).unwrap();
1558 assert_eq!(grpc.call, "grpc");
1559 assert!(grpc.with.authentication.is_some());
1560 match grpc.with.authentication.unwrap() {
1561 ReferenceableAuthenticationPolicy::Reference(r) => {
1562 assert_eq!(r.use_, "my-auth");
1563 }
1564 _ => panic!("Expected Reference variant"),
1565 }
1566 }
1567
1568 #[test]
1569 fn test_call_asyncapi_channel() {
1570 let json = r#"{
1572 "call": "asyncapi",
1573 "with": {
1574 "document": {"endpoint": "http://example.com/asyncapi.json"},
1575 "channel": "user-events",
1576 "protocol": "kafka",
1577 "message": {"payload": {"event": "created"}}
1578 }
1579 }"#;
1580 let asyncapi: CallAsyncAPIDefinition = serde_json::from_str(json).unwrap();
1581 assert_eq!(asyncapi.with.channel, Some("user-events".to_string()));
1582 assert!(asyncapi.with.message.is_some());
1583 }
1584}