toasty_driver_integration_suite/tests/
serialize.rs

1use crate::prelude::*;
2
3use serde::{Deserialize, Serialize};
4use std::collections::HashMap;
5use toasty_core::{
6    driver::{Operation, Rows},
7    stmt::{ExprSet, Statement, Value},
8};
9
10#[driver_test(id(ID))]
11pub async fn serialize_vec_string(t: &mut Test) -> Result<(), BoxError> {
12    #[derive(Debug, toasty::Model)]
13    struct Item {
14        #[key]
15        #[auto]
16        id: ID,
17        #[serialize(json)]
18        tags: Vec<String>,
19    }
20
21    let mut db = t.setup_db(models!(Item)).await;
22
23    // Insert — driver receives JSON string
24    t.log().clear();
25    let tags = vec!["rust".to_string(), "toasty".to_string()];
26    let expected_json = serde_json::to_string(&tags).unwrap();
27    let mut record = Item::create().tags(tags.clone()).exec(&mut db).await?;
28
29    let (op, _) = t.log().pop();
30    assert_struct!(op, Operation::QuerySql(_ {
31        stmt: Statement::Insert(_ {
32            source.body: ExprSet::Values(_ {
33                rows: [=~ (Any, expected_json)],
34                ..
35            }),
36            ..
37        }),
38        ..
39    }));
40
41    assert_eq!(Item::get_by_id(&mut db, &record.id).await?.tags, tags);
42
43    // Update — driver receives JSON string
44    t.log().clear();
45    let new_tags = vec!["b".to_string(), "c".to_string()];
46    let expected_json = serde_json::to_string(&new_tags).unwrap();
47    record.update().tags(new_tags.clone()).exec(&mut db).await?;
48
49    let (op, resp) = t.log().pop();
50    if t.capability().sql {
51        assert_struct!(op, Operation::QuerySql(_ {
52            stmt: Statement::Update(_ {
53                assignments: #{ 1: _ { expr: == expected_json, .. }},
54                ..
55            }),
56            ..
57        }));
58    } else {
59        assert_struct!(op, Operation::UpdateByKey(_ {
60            assignments: #{ 1: _ { expr: == expected_json, .. }},
61            ..
62        }));
63    }
64    assert_struct!(resp, _ { rows: Rows::Count(1), .. });
65
66    assert_eq!(Item::get_by_id(&mut db, &record.id).await?.tags, new_tags);
67
68    Ok(())
69}
70
71#[driver_test(id(ID))]
72pub async fn serialize_nullable(t: &mut Test) -> Result<(), BoxError> {
73    #[derive(Debug, toasty::Model)]
74    struct Item {
75        #[key]
76        #[auto]
77        id: ID,
78        #[serialize(json, nullable)]
79        data: Option<HashMap<String, String>>,
80    }
81
82    let mut db = t.setup_db(models!(Item)).await;
83
84    // Some — driver receives JSON string
85    t.log().clear();
86    let map = HashMap::from([("key".to_string(), "value".to_string())]);
87    let expected_json = serde_json::to_string(&map).unwrap();
88    let record = Item::create().data(Some(map.clone())).exec(&mut db).await?;
89
90    let (op, _) = t.log().pop();
91    assert_struct!(op, Operation::QuerySql(_ {
92        stmt: Statement::Insert(_ {
93            source.body: ExprSet::Values(_ {
94                rows: [=~ (Any, expected_json)],
95                ..
96            }),
97            ..
98        }),
99        ..
100    }));
101
102    assert_eq!(Item::get_by_id(&mut db, &record.id).await?.data, Some(map));
103
104    // None — driver receives SQL NULL
105    t.log().clear();
106    let empty_record = Item::create().data(None).exec(&mut db).await?;
107
108    let (op, _) = t.log().pop();
109    assert_struct!(op, Operation::QuerySql(_ {
110        stmt: Statement::Insert(_ {
111            source.body: ExprSet::Values(_ {
112                rows: [=~ (Any, Value::Null)],
113                ..
114            }),
115            ..
116        }),
117        ..
118    }));
119
120    assert_eq!(Item::get_by_id(&mut db, &empty_record.id).await?.data, None);
121
122    Ok(())
123}
124
125#[driver_test(id(ID))]
126pub async fn serialize_non_nullable_option(t: &mut Test) -> Result<(), BoxError> {
127    #[derive(Debug, toasty::Model)]
128    struct Item {
129        #[key]
130        #[auto]
131        id: ID,
132        #[serialize(json)]
133        extra: Option<String>,
134    }
135
136    let mut db = t.setup_db(models!(Item)).await;
137
138    // None → JSON text "null", not SQL NULL
139    t.log().clear();
140    let empty_record = Item::create().extra(None).exec(&mut db).await?;
141
142    let (op, _) = t.log().pop();
143    assert_struct!(op, Operation::QuerySql(_ {
144        stmt: Statement::Insert(_ {
145            source.body: ExprSet::Values(_ {
146                rows: [=~ (Any, "null")],
147                ..
148            }),
149            ..
150        }),
151        ..
152    }));
153
154    assert_eq!(
155        Item::get_by_id(&mut db, &empty_record.id).await?.extra,
156        None
157    );
158
159    // Some → JSON string with quotes
160    t.log().clear();
161    let expected_json = serde_json::to_string(&Some("hello")).unwrap();
162    let record = Item::create()
163        .extra(Some("hello".to_string()))
164        .exec(&mut db)
165        .await?;
166
167    let (op, _) = t.log().pop();
168    assert_struct!(op, Operation::QuerySql(_ {
169        stmt: Statement::Insert(_ {
170            source.body: ExprSet::Values(_ {
171                rows: [=~ (Any, expected_json)],
172                ..
173            }),
174            ..
175        }),
176        ..
177    }));
178
179    assert_eq!(
180        Item::get_by_id(&mut db, &record.id).await?.extra,
181        Some("hello".to_string())
182    );
183
184    Ok(())
185}
186
187#[driver_test(id(ID))]
188pub async fn serialize_custom_struct(t: &mut Test) -> Result<(), BoxError> {
189    #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
190    struct Metadata {
191        version: u32,
192        labels: Vec<String>,
193    }
194
195    #[derive(Debug, toasty::Model)]
196    struct Item {
197        #[key]
198        #[auto]
199        id: ID,
200        #[serialize(json)]
201        meta: Metadata,
202    }
203
204    let mut db = t.setup_db(models!(Item)).await;
205    t.log().clear();
206
207    let meta = Metadata {
208        version: 42,
209        labels: vec!["alpha".to_string(), "beta".to_string()],
210    };
211    let expected_json = serde_json::to_string(&meta).unwrap();
212    let record = Item::create().meta(meta.clone()).exec(&mut db).await?;
213
214    let (op, _) = t.log().pop();
215    assert_struct!(op, Operation::QuerySql(_ {
216        stmt: Statement::Insert(_ {
217            source.body: ExprSet::Values(_ {
218                rows: [=~ (Any, expected_json)],
219                ..
220            }),
221            ..
222        }),
223        ..
224    }));
225
226    assert_eq!(Item::get_by_id(&mut db, &record.id).await?.meta, meta);
227
228    Ok(())
229}