]> Untitled Git - lemmy.git/blob - crates/db_queries/src/aggregates/post_aggregates.rs
Move most code into crates/ subfolder
[lemmy.git] / crates / db_queries / src / aggregates / post_aggregates.rs
1 use diesel::{result::Error, *};
2 use lemmy_db_schema::schema::post_aggregates;
3 use serde::Serialize;
4
5 #[derive(Queryable, Associations, Identifiable, PartialEq, Debug, Serialize, Clone)]
6 #[table_name = "post_aggregates"]
7 pub struct PostAggregates {
8   pub id: i32,
9   pub post_id: i32,
10   pub comments: i64,
11   pub score: i64,
12   pub upvotes: i64,
13   pub downvotes: i64,
14   pub stickied: bool,
15   pub published: chrono::NaiveDateTime,
16   pub newest_comment_time: chrono::NaiveDateTime,
17 }
18
19 impl PostAggregates {
20   pub fn read(conn: &PgConnection, post_id: i32) -> Result<Self, Error> {
21     post_aggregates::table
22       .filter(post_aggregates::post_id.eq(post_id))
23       .first::<Self>(conn)
24   }
25 }
26
27 #[cfg(test)]
28 mod tests {
29   use crate::{
30     aggregates::post_aggregates::PostAggregates,
31     establish_unpooled_connection,
32     Crud,
33     Likeable,
34     ListingType,
35     SortType,
36   };
37   use lemmy_db_schema::source::{
38     comment::{Comment, CommentForm},
39     community::{Community, CommunityForm},
40     post::{Post, PostForm, PostLike, PostLikeForm},
41     user::{UserForm, User_},
42   };
43
44   #[test]
45   fn test_crud() {
46     let conn = establish_unpooled_connection();
47
48     let new_user = UserForm {
49       name: "thommy_community_agg".into(),
50       preferred_username: None,
51       password_encrypted: "nope".into(),
52       email: None,
53       matrix_user_id: None,
54       avatar: None,
55       banner: None,
56       admin: false,
57       banned: Some(false),
58       published: None,
59       updated: None,
60       show_nsfw: false,
61       theme: "browser".into(),
62       default_sort_type: SortType::Hot as i16,
63       default_listing_type: ListingType::Subscribed as i16,
64       lang: "browser".into(),
65       show_avatars: true,
66       send_notifications_to_email: false,
67       actor_id: None,
68       bio: None,
69       local: true,
70       private_key: None,
71       public_key: None,
72       last_refreshed_at: None,
73     };
74
75     let inserted_user = User_::create(&conn, &new_user).unwrap();
76
77     let another_user = UserForm {
78       name: "jerry_community_agg".into(),
79       preferred_username: None,
80       password_encrypted: "nope".into(),
81       email: None,
82       matrix_user_id: None,
83       avatar: None,
84       banner: None,
85       admin: false,
86       banned: Some(false),
87       published: None,
88       updated: None,
89       show_nsfw: false,
90       theme: "browser".into(),
91       default_sort_type: SortType::Hot as i16,
92       default_listing_type: ListingType::Subscribed as i16,
93       lang: "browser".into(),
94       show_avatars: true,
95       send_notifications_to_email: false,
96       actor_id: None,
97       bio: None,
98       local: true,
99       private_key: None,
100       public_key: None,
101       last_refreshed_at: None,
102     };
103
104     let another_inserted_user = User_::create(&conn, &another_user).unwrap();
105
106     let new_community = CommunityForm {
107       name: "TIL_community_agg".into(),
108       creator_id: inserted_user.id,
109       title: "nada".to_owned(),
110       description: None,
111       category_id: 1,
112       nsfw: false,
113       removed: None,
114       deleted: None,
115       updated: None,
116       actor_id: None,
117       local: true,
118       private_key: None,
119       public_key: None,
120       last_refreshed_at: None,
121       published: None,
122       icon: None,
123       banner: None,
124     };
125
126     let inserted_community = Community::create(&conn, &new_community).unwrap();
127
128     let new_post = PostForm {
129       name: "A test post".into(),
130       url: None,
131       body: None,
132       creator_id: inserted_user.id,
133       community_id: inserted_community.id,
134       removed: None,
135       deleted: None,
136       locked: None,
137       stickied: None,
138       nsfw: false,
139       updated: None,
140       embed_title: None,
141       embed_description: None,
142       embed_html: None,
143       thumbnail_url: None,
144       ap_id: None,
145       local: true,
146       published: None,
147     };
148
149     let inserted_post = Post::create(&conn, &new_post).unwrap();
150
151     let comment_form = CommentForm {
152       content: "A test comment".into(),
153       creator_id: inserted_user.id,
154       post_id: inserted_post.id,
155       removed: None,
156       deleted: None,
157       read: None,
158       parent_id: None,
159       published: None,
160       updated: None,
161       ap_id: None,
162       local: true,
163     };
164
165     let inserted_comment = Comment::create(&conn, &comment_form).unwrap();
166
167     let child_comment_form = CommentForm {
168       content: "A test comment".into(),
169       creator_id: inserted_user.id,
170       post_id: inserted_post.id,
171       removed: None,
172       deleted: None,
173       read: None,
174       parent_id: Some(inserted_comment.id),
175       published: None,
176       updated: None,
177       ap_id: None,
178       local: true,
179     };
180
181     let _inserted_child_comment = Comment::create(&conn, &child_comment_form).unwrap();
182
183     let post_like = PostLikeForm {
184       post_id: inserted_post.id,
185       user_id: inserted_user.id,
186       score: 1,
187     };
188
189     PostLike::like(&conn, &post_like).unwrap();
190
191     let post_aggs_before_delete = PostAggregates::read(&conn, inserted_post.id).unwrap();
192
193     assert_eq!(2, post_aggs_before_delete.comments);
194     assert_eq!(1, post_aggs_before_delete.score);
195     assert_eq!(1, post_aggs_before_delete.upvotes);
196     assert_eq!(0, post_aggs_before_delete.downvotes);
197
198     // Add a post dislike from the other user
199     let post_dislike = PostLikeForm {
200       post_id: inserted_post.id,
201       user_id: another_inserted_user.id,
202       score: -1,
203     };
204
205     PostLike::like(&conn, &post_dislike).unwrap();
206
207     let post_aggs_after_dislike = PostAggregates::read(&conn, inserted_post.id).unwrap();
208
209     assert_eq!(2, post_aggs_after_dislike.comments);
210     assert_eq!(0, post_aggs_after_dislike.score);
211     assert_eq!(1, post_aggs_after_dislike.upvotes);
212     assert_eq!(1, post_aggs_after_dislike.downvotes);
213
214     // Remove the parent comment
215     Comment::delete(&conn, inserted_comment.id).unwrap();
216     let after_comment_delete = PostAggregates::read(&conn, inserted_post.id).unwrap();
217     assert_eq!(0, after_comment_delete.comments);
218     assert_eq!(0, after_comment_delete.score);
219     assert_eq!(1, after_comment_delete.upvotes);
220     assert_eq!(1, after_comment_delete.downvotes);
221
222     // Remove the first post like
223     PostLike::remove(&conn, inserted_user.id, inserted_post.id).unwrap();
224     let after_like_remove = PostAggregates::read(&conn, inserted_post.id).unwrap();
225     assert_eq!(0, after_like_remove.comments);
226     assert_eq!(-1, after_like_remove.score);
227     assert_eq!(0, after_like_remove.upvotes);
228     assert_eq!(1, after_like_remove.downvotes);
229
230     // This should delete all the associated rows, and fire triggers
231     User_::delete(&conn, another_inserted_user.id).unwrap();
232     let user_num_deleted = User_::delete(&conn, inserted_user.id).unwrap();
233     assert_eq!(1, user_num_deleted);
234
235     // Should be none found, since the creator was deleted
236     let after_delete = PostAggregates::read(&conn, inserted_post.id);
237     assert!(after_delete.is_err());
238   }
239 }