Skip to main content

serde_patch/
lib.rs

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(), // igual em new
67                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}