toasty_driver_integration_suite/tests/
deferred_embed.rs1use crate::prelude::*;
2
3#[driver_test(id(ID), scenario(crate::scenarios::document_deferred_metadata))]
6pub async fn deferred_embed_struct(t: &mut Test) -> Result<()> {
7 let mut db = setup(t).await;
8
9 let created = toasty::create!(Document {
10 title: "Hello".to_string(),
11 metadata: Metadata {
12 author: "Alice".to_string(),
13 notes: "Important".to_string(),
14 },
15 })
16 .exec(&mut db)
17 .await?;
18
19 assert_eq!("Hello", created.title);
22 assert_eq!("Alice", created.metadata.get().author);
23 assert_eq!("Important", created.metadata.get().notes);
24
25 let read = Document::filter_by_id(created.id).get(&mut db).await?;
27 assert_eq!("Hello", read.title);
28 assert!(read.metadata.is_unloaded());
29
30 let read_with = Document::filter_by_id(created.id)
32 .include(Document::fields().metadata())
33 .get(&mut db)
34 .await?;
35 assert!(!read_with.metadata.is_unloaded());
36 assert_eq!("Alice", read_with.metadata.get().author);
37 assert_eq!("Important", read_with.metadata.get().notes);
38
39 Ok(())
40}
41
42#[driver_test(id(ID), scenario(crate::scenarios::person_contact_deferred_metadata))]
55pub async fn deferred_inside_embed_in_enum_variant(t: &mut Test) -> Result<()> {
56 let mut db = setup(t).await;
57
58 let created = toasty::create!(Person {
61 name: "Alice".to_string(),
62 contact: ContactInfo::Email {
63 address: "alice@example.com".to_string(),
64 metadata: Metadata {
65 author: "Alice".to_string(),
66 notes: "Important".to_string().into(),
67 },
68 },
69 })
70 .exec(&mut db)
71 .await?;
72
73 let ContactInfo::Email {
74 address, metadata, ..
75 } = &created.contact
76 else {
77 panic!("expected Email variant");
78 };
79 assert_eq!("alice@example.com", address);
80 assert_eq!("Alice", metadata.author);
81 assert_eq!("Important", metadata.notes.get());
82
83 let read = Person::filter_by_id(created.id).get(&mut db).await?;
86 let ContactInfo::Email { metadata, .. } = &read.contact else {
87 panic!("expected Email variant");
88 };
89 assert_eq!("Alice", metadata.author);
90 assert!(metadata.notes.is_unloaded());
91
92 Ok(())
93}
94
95#[driver_test(id(ID), scenario(crate::scenarios::person_contact_deferred_metadata))]
102pub async fn include_deferred_inside_embed_in_enum_variant(t: &mut Test) -> Result<()> {
103 let mut db = setup(t).await;
104
105 let alice = toasty::create!(Person {
106 name: "Alice".to_string(),
107 contact: ContactInfo::Email {
108 address: "alice@example.com".to_string(),
109 metadata: Metadata {
110 author: "Alice".to_string(),
111 notes: "Important".to_string().into(),
112 },
113 },
114 })
115 .exec(&mut db)
116 .await?;
117
118 let bob = toasty::create!(Person {
121 name: "Bob".to_string(),
122 contact: ContactInfo::Phone {
123 number: "555-0100".to_string(),
124 },
125 })
126 .exec(&mut db)
127 .await?;
128
129 let alice_read = Person::filter_by_id(alice.id)
131 .include(Person::fields().contact().email().metadata().notes())
132 .get(&mut db)
133 .await?;
134 let ContactInfo::Email { metadata, .. } = &alice_read.contact else {
135 panic!("expected Email variant");
136 };
137 assert_eq!("Alice", metadata.author);
138 assert!(!metadata.notes.is_unloaded());
139 assert_eq!("Important", metadata.notes.get());
140
141 let bob_read = Person::filter_by_id(bob.id)
144 .include(Person::fields().contact().email().metadata().notes())
145 .get(&mut db)
146 .await?;
147 let ContactInfo::Phone { number } = &bob_read.contact else {
148 panic!("expected Phone variant");
149 };
150 assert_eq!("555-0100", number);
151
152 Ok(())
153}
154
155#[driver_test(id(ID))]
158pub async fn deferred_embed_unit_enum(t: &mut Test) -> Result<()> {
159 #[derive(Debug, PartialEq, toasty::Embed)]
160 enum Status {
161 Draft,
162 Published,
163 Archived,
164 }
165
166 #[derive(Debug, toasty::Model)]
167 struct Document {
168 #[key]
169 #[auto]
170 id: ID,
171
172 title: String,
173 status: toasty::Deferred<Status>,
174 }
175
176 let mut db = t.setup_db(models!(Document)).await;
177
178 let created = toasty::create!(Document {
179 title: "Hello".to_string(),
180 status: Status::Published,
181 })
182 .exec(&mut db)
183 .await?;
184
185 assert_eq!(&Status::Published, created.status.get());
186
187 let read = Document::filter_by_id(created.id).get(&mut db).await?;
188 assert!(read.status.is_unloaded());
189
190 let inc = Document::filter_by_id(created.id)
191 .include(Document::fields().status())
192 .get(&mut db)
193 .await?;
194 assert!(!inc.status.is_unloaded());
195 assert_eq!(&Status::Published, inc.status.get());
196
197 Ok(())
198}
199
200#[driver_test(id(ID))]
203pub async fn deferred_embed_data_enum(t: &mut Test) -> Result<()> {
204 #[derive(Debug, PartialEq, toasty::Embed)]
205 enum ContactInfo {
206 Email { address: String },
207 Phone { number: String },
208 Mail,
209 }
210
211 #[derive(Debug, toasty::Model)]
212 struct Person {
213 #[key]
214 #[auto]
215 id: ID,
216
217 name: String,
218 contact: toasty::Deferred<ContactInfo>,
219 }
220
221 let mut db = t.setup_db(models!(Person)).await;
222
223 let alice = toasty::create!(Person {
224 name: "Alice".to_string(),
225 contact: ContactInfo::Email {
226 address: "alice@example.com".to_string(),
227 },
228 })
229 .exec(&mut db)
230 .await?;
231
232 let bob = toasty::create!(Person {
233 name: "Bob".to_string(),
234 contact: ContactInfo::Mail,
235 })
236 .exec(&mut db)
237 .await?;
238
239 assert_eq!(
240 &ContactInfo::Email {
241 address: "alice@example.com".to_string()
242 },
243 alice.contact.get()
244 );
245
246 let read = Person::filter_by_id(alice.id).get(&mut db).await?;
247 assert!(read.contact.is_unloaded());
248
249 let inc = Person::filter_by_id(alice.id)
250 .include(Person::fields().contact())
251 .get(&mut db)
252 .await?;
253 assert!(!inc.contact.is_unloaded());
254 assert_eq!(
255 &ContactInfo::Email {
256 address: "alice@example.com".to_string()
257 },
258 inc.contact.get()
259 );
260
261 let inc_bob = Person::filter_by_id(bob.id)
262 .include(Person::fields().contact())
263 .get(&mut db)
264 .await?;
265 assert_eq!(&ContactInfo::Mail, inc_bob.contact.get());
266
267 Ok(())
268}
269
270#[driver_test(id(ID), scenario(crate::scenarios::document_deferred_metadata))]
273pub async fn deferred_embed_update_reloads(t: &mut Test) -> Result<()> {
274 let mut db = setup(t).await;
275
276 let created = toasty::create!(Document {
277 title: "Hello".to_string(),
278 metadata: Metadata {
279 author: "Alice".to_string(),
280 notes: "old".to_string(),
281 },
282 })
283 .exec(&mut db)
284 .await?;
285
286 let mut doc = Document::filter_by_id(created.id).get(&mut db).await?;
287 assert!(doc.metadata.is_unloaded());
288
289 doc.update()
290 .metadata(Metadata {
291 author: "Bob".to_string(),
292 notes: "new".to_string(),
293 })
294 .exec(&mut db)
295 .await?;
296
297 assert!(!doc.metadata.is_unloaded());
299 assert_eq!("Bob", doc.metadata.get().author);
300 assert_eq!("new", doc.metadata.get().notes);
301
302 Ok(())
303}
304
305#[driver_test(id(ID))]
313pub async fn deferred_embed_with_deferred_sub_field(t: &mut Test) -> Result<()> {
314 #[derive(Debug, toasty::Embed)]
315 struct Metadata {
316 author: String,
317 notes: toasty::Deferred<String>,
318 }
319
320 #[derive(Debug, toasty::Model)]
321 struct Document {
322 #[key]
323 #[auto]
324 id: ID,
325
326 title: String,
327 metadata: toasty::Deferred<Metadata>,
328 }
329
330 let mut db = t.setup_db(models!(Document)).await;
331
332 let created = toasty::create!(Document {
333 title: "Hello".to_string(),
334 metadata: Metadata {
335 author: "Alice".to_string(),
336 notes: "Important".to_string().into(),
337 },
338 })
339 .exec(&mut db)
340 .await?;
341
342 assert_eq!("Alice", created.metadata.get().author);
344 assert_eq!("Important", created.metadata.get().notes.get());
345
346 let read = Document::filter_by_id(created.id).get(&mut db).await?;
348 assert!(read.metadata.is_unloaded());
349
350 let inc_outer = Document::filter_by_id(created.id)
353 .include(Document::fields().metadata())
354 .get(&mut db)
355 .await?;
356 assert!(!inc_outer.metadata.is_unloaded());
357 assert_eq!("Alice", inc_outer.metadata.get().author);
358 assert!(inc_outer.metadata.get().notes.is_unloaded());
359
360 let inc_inner = Document::filter_by_id(created.id)
363 .include(Document::fields().metadata().notes())
364 .get(&mut db)
365 .await?;
366 assert!(!inc_inner.metadata.is_unloaded());
367 assert_eq!("Alice", inc_inner.metadata.get().author);
368 assert!(!inc_inner.metadata.get().notes.is_unloaded());
369 assert_eq!("Important", inc_inner.metadata.get().notes.get());
370
371 Ok(())
372}
373
374#[driver_test(id(ID), scenario(crate::scenarios::document_metadata_deferred_notes))]
377pub async fn deferred_field_inside_embed(t: &mut Test) -> Result<()> {
378 let mut db = setup(t).await;
379
380 let created = toasty::create!(Document {
381 title: "Hello".to_string(),
382 metadata: Metadata {
383 author: "Alice".to_string(),
384 notes: "Important".to_string().into(),
385 },
386 })
387 .exec(&mut db)
388 .await?;
389
390 assert_eq!("Alice", created.metadata.author);
392 assert_eq!("Important", created.metadata.notes.get());
393
394 let read = Document::filter_by_id(created.id).get(&mut db).await?;
396 assert_eq!("Alice", read.metadata.author);
397 assert!(read.metadata.notes.is_unloaded());
398
399 let inc = Document::filter_by_id(created.id)
401 .include(Document::fields().metadata().notes())
402 .get(&mut db)
403 .await?;
404 assert!(!inc.metadata.notes.is_unloaded());
405 assert_eq!("Important", inc.metadata.notes.get());
406
407 Ok(())
408}
409
410#[driver_test(id(ID), scenario(crate::scenarios::document_metadata_deferred_notes))]
416pub async fn update_embed_by_value_with_deferred_sub_field(t: &mut Test) -> Result<()> {
417 let mut db = setup(t).await;
418
419 let mut doc = toasty::create!(Document {
420 title: "Hello".to_string(),
421 metadata: Metadata {
422 author: "Alice".to_string(),
423 notes: "old".to_string().into(),
424 },
425 })
426 .exec(&mut db)
427 .await?;
428
429 doc.update()
430 .metadata(Metadata {
431 author: "Bob".to_string(),
432 notes: "new".to_string().into(),
433 })
434 .exec(&mut db)
435 .await?;
436
437 assert_eq!("Bob", doc.metadata.author);
439 assert_eq!("new", doc.metadata.notes.get());
440
441 let reread = Document::filter_by_id(doc.id)
444 .include(Document::fields().metadata().notes())
445 .get(&mut db)
446 .await?;
447 assert_eq!("Bob", reread.metadata.author);
448 assert_eq!("new", reread.metadata.notes.get());
449
450 Ok(())
451}
452
453#[driver_test(
460 id(ID),
461 scenario(crate::scenarios::document_optional_metadata_deferred_notes)
462)]
463pub async fn deferred_field_inside_option_embed(t: &mut Test) -> Result<()> {
464 let mut db = setup(t).await;
465
466 let created = toasty::create!(Document {
467 title: "Hello".to_string(),
468 metadata: Some(Metadata {
469 author: "Alice".to_string(),
470 notes: "Important".to_string().into(),
471 }),
472 })
473 .exec(&mut db)
474 .await?;
475
476 let md = created.metadata.as_ref().expect("Some");
478 assert_eq!("Alice", md.author);
479 assert_eq!("Important", md.notes.get());
480
481 let read = Document::filter_by_id(created.id).get(&mut db).await?;
483 let md = read.metadata.as_ref().expect("Some");
484 assert_eq!("Alice", md.author);
485 assert!(md.notes.is_unloaded());
486
487 let empty = toasty::create!(Document {
489 title: "Empty".to_string(),
490 metadata: None,
491 })
492 .exec(&mut db)
493 .await?;
494 assert!(empty.metadata.is_none());
495
496 Ok(())
497}
498
499#[driver_test(id(ID), scenario(crate::scenarios::document_optional_body_deferred))]
506pub async fn deferred_newtype_inside_option_embed(t: &mut Test) -> Result<()> {
507 let mut db = setup(t).await;
508
509 let created = toasty::create!(Document {
510 title: "Hello".to_string(),
511 body: Some(Body("Important".to_string().into())),
512 })
513 .exec(&mut db)
514 .await?;
515
516 let body = created.body.as_ref().expect("Some");
518 assert_eq!("Important", body.0.get());
519
520 let read = Document::filter_by_id(created.id).get(&mut db).await?;
522 let body = read.body.as_ref().expect("Some");
523 assert!(body.0.is_unloaded());
524
525 let empty = toasty::create!(Document {
527 title: "Empty".to_string(),
528 body: None,
529 })
530 .exec(&mut db)
531 .await?;
532 assert!(empty.body.is_none());
533
534 Ok(())
535}