1pub mod apply_patch;
2pub mod apply_patch_mut;
3pub mod diff_patch;
4
5#[cfg(test)]
6mod tests {
7 use crate::{apply, apply_mut, diff};
8 use serde::{Deserialize, Serialize};
9 use serde_json::json;
10
11 #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
12 struct Profile {
13 bio: String,
14 avatar_url: Option<String>,
15 }
16
17 #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
18 struct User {
19 id: u32,
20 username: String,
21 age: u8,
22 active: bool,
23 profile: Option<Profile>,
24 }
25
26 #[test]
27 fn test_diff() {
28 let old = User {
29 id: 1001,
30 username: "alice".to_string(),
31 age: 30,
32 active: true,
33 profile: Some(Profile {
34 bio: "Software engineer".to_string(),
35 avatar_url: Some("https://example.com/alice-old.jpg".to_string()),
36 }),
37 };
38
39 let new = User {
40 id: 1001,
41 username: "alice".to_string(),
42 age: 31,
43 active: false,
44 profile: Some(Profile {
45 bio: "Senior software engineer".to_string(),
46 avatar_url: None,
47 }),
48 };
49
50 let patch = serde_json::to_string(&diff!(&old, &new; ["id"]).unwrap()).unwrap();
51
52 assert_eq!(
53 patch,
54 r#"{"active":false,"age":31,"id":1001,"profile":{"avatar_url":null,"bio":"Senior software engineer"}}"#
55 );
56 }
57
58 #[test]
59 fn test_diff_forced_nested() {
60 let old = User {
61 id: 1001,
62 username: "alice".to_string(),
63 age: 30,
64 active: true,
65 profile: Some(Profile {
66 bio: "Software engineer".to_string(), avatar_url: Some("https://example.com/alice-old.jpg".to_string()),
68 }),
69 };
70 let new = User {
71 id: 1001,
72 username: "alice".to_string(),
73 age: 31,
74 active: false,
75 profile: Some(Profile {
76 bio: "Software engineer".to_string(),
77 avatar_url: None,
78 }),
79 };
80
81 let patch_value = diff!(&old, &new; ["profile.bio"]).unwrap();
82
83 let expected = json!({
84 "age": 31,
85 "active": false,
86 "profile": {
87 "bio": "Software engineer",
88 "avatar_url": null
89 }
90 });
91
92 assert_eq!(patch_value, expected);
93 }
94
95 #[test]
96 fn test_apply_patch_immutable() {
97 let current = User {
98 id: 1001,
99 username: "alice".to_string(),
100 age: 30,
101 active: true,
102 profile: Some(Profile {
103 bio: "Software engineer".to_string(),
104 avatar_url: Some("https://example.com/alice-old.jpg".to_string()),
105 }),
106 };
107
108 let patch = r#"
109 {
110 "age": 31,
111 "active": false,
112 "profile": {
113 "bio": "Senior software engineer",
114 "avatar_url": null
115 }
116 }
117 "#;
118
119 let updated: User = apply!(current, patch).unwrap();
120
121 assert_eq!(
122 updated,
123 User {
124 id: 1001,
125 username: "alice".to_string(),
126 age: 31,
127 active: false,
128 profile: Some(Profile {
129 bio: "Senior software engineer".to_string(),
130 avatar_url: None,
131 }),
132 }
133 );
134 }
135
136 #[test]
137 fn test_apply_patch_mutable() {
138 let mut current = User {
139 id: 1001,
140 username: "alice".to_string(),
141 age: 30,
142 active: true,
143 profile: Some(Profile {
144 bio: "Software engineer".to_string(),
145 avatar_url: Some("https://example.com/alice-old.jpg".to_string()),
146 }),
147 };
148
149 let patch = r#"
150 {
151 "age": 31,
152 "active": false,
153 "profile": {
154 "bio": "Senior software engineer",
155 "avatar_url": null
156 }
157 }
158 "#;
159
160 apply_mut!(&mut current, patch).unwrap();
161
162 assert_eq!(
163 current,
164 User {
165 id: 1001,
166 username: "alice".to_string(),
167 age: 31,
168 active: false,
169 profile: Some(Profile {
170 bio: "Senior software engineer".to_string(),
171 avatar_url: None,
172 }),
173 }
174 );
175 }
176}