toasty_driver_integration_suite/tests/
embed_enum_variant_patch.rs1use crate::prelude::*;
8use toasty::stmt;
9
10#[derive(Debug, PartialEq, toasty::Embed)]
11enum State {
12 Active { count: i64 },
13 Inactive,
14}
15
16#[derive(Debug, PartialEq, toasty::Embed)]
17enum Nested {
18 Wrapped { state: State },
19 Empty,
20}
21
22#[derive(Debug, PartialEq, toasty::Embed)]
25struct Details {
26 unrelated: i64,
27 state: State,
28 nested: Nested,
29}
30
31#[derive(Debug, toasty::Model)]
32struct Item {
33 #[key]
34 #[auto]
35 id: uuid::Uuid,
36 name: String,
37 details: Details,
38}
39
40fn initial_details() -> Details {
41 Details {
42 unrelated: 1,
43 state: State::Active { count: 5 },
44 nested: Nested::Wrapped {
45 state: State::Active { count: 7 },
46 },
47 }
48}
49
50async fn setup(t: &mut Test) -> Result<(toasty::Db, Item)> {
51 let mut db = t.setup_db(models!(Item)).await;
52 let item = toasty::create!(Item {
53 name: "before",
54 details: initial_details(),
55 })
56 .exec(&mut db)
57 .await?;
58 Ok((db, item))
59}
60
61async fn assert_rejected(
66 t: &Test,
67 db: &mut toasty::Db,
68 item: &Item,
69 patch: stmt::Assignment<Details>,
70) -> Result<()> {
71 t.log().clear();
72 let err = assert_err!(
73 Item::filter_by_id(item.id)
74 .update()
75 .name("after")
76 .details(patch)
77 .exec(db)
78 .await
79 );
80 assert!(err.is_unsupported_feature(), "{err}");
81 assert!(t.log().is_empty());
82
83 let found = Item::get_by_id(db, item.id).await?;
84 assert_eq!(found.name, "before");
85 assert_eq!(found.details, initial_details());
86 Ok(())
87}
88
89#[driver_test]
90pub async fn reject_set_through_variant(t: &mut Test) -> Result<()> {
91 let (mut db, item) = setup(t).await?;
92 let patch = stmt::patch(Details::fields().state().active().count(), 9);
93 assert_rejected(t, &mut db, &item, patch).await
94}
95
96#[driver_test]
97pub async fn reject_increment_through_variant(t: &mut Test) -> Result<()> {
98 let (mut db, item) = setup(t).await?;
99 let patch = stmt::patch(
100 Details::fields().state().active().count(),
101 stmt::increment(),
102 );
103 assert_rejected(t, &mut db, &item, patch).await
104}
105
106#[driver_test]
107pub async fn reject_patch_through_nested_variants(t: &mut Test) -> Result<()> {
108 let (mut db, item) = setup(t).await?;
109 let count = || {
110 Details::fields()
111 .nested()
112 .wrapped()
113 .state()
114 .active()
115 .count()
116 };
117
118 assert_rejected(t, &mut db, &item, stmt::patch(count(), 9)).await?;
119 assert_rejected(t, &mut db, &item, stmt::patch(count(), stmt::increment())).await
120}
121
122#[driver_test]
125pub async fn patch_beside_variant_boundary(t: &mut Test) -> Result<()> {
126 let (mut db, mut item) = setup(t).await?;
127
128 item.update()
129 .details(stmt::apply([
130 stmt::patch(Details::fields().unrelated(), stmt::increment()),
131 stmt::patch(Details::fields().state().into(), State::Inactive),
132 ]))
133 .exec(&mut db)
134 .await?;
135 assert_eq!(
136 Item::get_by_id(&mut db, item.id).await?.details,
137 Details {
138 unrelated: 2,
139 state: State::Inactive,
140 nested: Nested::Wrapped {
141 state: State::Active { count: 7 },
142 },
143 }
144 );
145
146 item.update()
147 .details(stmt::patch(
148 Details::fields().nested().into(),
149 Nested::Wrapped {
150 state: State::Active { count: 8 },
151 },
152 ))
153 .exec(&mut db)
154 .await?;
155 assert_eq!(
156 Item::get_by_id(&mut db, item.id).await?.details,
157 Details {
158 unrelated: 2,
159 state: State::Inactive,
160 nested: Nested::Wrapped {
161 state: State::Active { count: 8 },
162 },
163 }
164 );
165
166 Ok(())
167}