1use jacquard_derive::open_union;
2use serde::{Deserialize, Serialize};
3
4#[open_union]
5#[derive(Serialize, Deserialize, Debug, PartialEq)]
6#[serde(tag = "$type")]
7enum TestUnion<'s> {
8 #[serde(rename = "com.example.typeA")]
9 TypeA { value: &'s str },
10 #[serde(rename = "com.example.typeB")]
11 TypeB { count: i64 },
12}
13
14#[test]
15fn test_open_union_known_variant() {
16 let json = r#"{"$type":"com.example.typeA","value":"hello"}"#;
17 let union: TestUnion = serde_json::from_str(json).unwrap();
18
19 match union {
20 TestUnion::TypeA { value } => assert_eq!(value, "hello"),
21 _ => panic!("expected TypeA"),
22 }
23}
24
25#[test]
26fn test_open_union_unknown_variant() {
27 use jacquard_common::types::value::Data;
28
29 let json = r#"{"$type":"com.example.unknown","data":"something"}"#;
30 let union: TestUnion = serde_json::from_str(json).unwrap();
31
32 match union {
33 TestUnion::Unknown(Data::Object(obj)) => {
34 // Verify the captured data contains the expected fields
35 assert!(obj.0.contains_key("$type"));
36 assert!(obj.0.contains_key("data"));
37
38 // Check the actual values
39 if let Some(Data::String(type_str)) = obj.0.get("$type") {
40 assert_eq!(type_str.as_str(), "com.example.unknown");
41 } else {
42 panic!("expected $type field to be a string");
43 }
44
45 if let Some(Data::String(data_str)) = obj.0.get("data") {
46 assert_eq!(data_str.as_str(), "something");
47 } else {
48 panic!("expected data field to be a string");
49 }
50 }
51 _ => panic!("expected Unknown variant with Object data"),
52 }
53}
54
55#[test]
56fn test_open_union_roundtrip() {
57 let union = TestUnion::TypeB { count: 42 };
58 let json = serde_json::to_string(&union).unwrap();
59 let parsed: TestUnion = serde_json::from_str(&json).unwrap();
60
61 assert_eq!(union, parsed);
62
63 // Verify the $type field is present
64 assert!(json.contains(r#""$type":"com.example.typeB""#));
65}
66
67#[test]
68fn test_open_union_unknown_roundtrip() {
69 use jacquard_common::types::value::{Data, Object};
70 use std::collections::BTreeMap;
71
72 // Create an Unknown variant with complex data
73 let mut map = BTreeMap::new();
74 map.insert(
75 "$type".into(),
76 Data::String(jacquard_common::types::string::AtprotoStr::String(
77 "com.example.custom".into(),
78 )),
79 );
80 map.insert("field1".into(), Data::Integer(123));
81 map.insert("field2".into(), Data::Boolean(false));
82
83 let union = TestUnion::Unknown(Data::Object(Object(map)));
84
85 let json = serde_json::to_string(&union).unwrap();
86 let parsed: TestUnion = serde_json::from_str(&json).unwrap();
87
88 // Should deserialize back as Unknown since the type is not recognized
89 match parsed {
90 TestUnion::Unknown(Data::Object(obj)) => {
91 assert_eq!(obj.0.len(), 3);
92 assert!(obj.0.contains_key("$type"));
93 assert!(obj.0.contains_key("field1"));
94 assert!(obj.0.contains_key("field2"));
95
96 // Verify values
97 if let Some(Data::String(s)) = obj.0.get("$type") {
98 assert_eq!(s.as_str(), "com.example.custom");
99 } else {
100 panic!("expected $type to be a string");
101 }
102
103 if let Some(Data::Integer(n)) = obj.0.get("field1") {
104 assert_eq!(*n, 123);
105 } else {
106 panic!("expected field1 to be an integer");
107 }
108
109 if let Some(Data::Boolean(b)) = obj.0.get("field2") {
110 assert_eq!(*b, false);
111 } else {
112 panic!("expected field2 to be a boolean");
113 }
114 }
115 _ => panic!("expected Unknown variant"),
116 }
117}