]> Untitled Git - lemmy.git/blob - crates/db_queries/src/aggregates/post_aggregates.rs
Still continuing on....
[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_necro: chrono::NaiveDateTime, // A newest comment time, limited to 2 days, to prevent necrobumping
17   pub newest_comment_time: chrono::NaiveDateTime,
18 }
19
20 impl PostAggregates {
21   pub fn read(conn: &PgConnection, post_id: i32) -> Result<Self, Error> {
22     post_aggregates::table
23       .filter(post_aggregates::post_id.eq(post_id))
24       .first::<Self>(conn)
25   }
26 }
27
28 #[cfg(test)]
29 mod tests {
30   use crate::{
31     aggregates::post_aggregates::PostAggregates,
32     establish_unpooled_connection,
33     Crud,
34   };
35   use lemmy_db_schema::source::{
36     comment::{Comment, CommentForm},
37     community::{Community, CommunityForm},
38     post::{Post, PostForm, PostLike, PostLikeForm},
39     person::{PersonForm, Person},
40   };
41
42   #[test]
43   fn test_crud() {
44     let conn = establish_unpooled_connection();
45
46     let new_person = PersonForm {
47       name: "thommy_community_agg".into(),
48       preferred_username: None,
49       avatar: None,
50       banner: None,
51       banned: Some(false),
52       deleted: false,
53       published: None,
54       updated: None,
55       actor_id: None,
56       bio: None,
57       local: true,
58       private_key: None,
59       public_key: None,
60       last_refreshed_at: None,
61       inbox_url: None,
62       shared_inbox_url: None,
63     };
64
65     let inserted_person = Person::create(&conn, &new_person).unwrap();
66
67     let another_person = PersonForm {
68       name: "jerry_community_agg".into(),
69       preferred_username: None,
70       avatar: None,
71       banner: None,
72       banned: Some(false),
73       deleted: false,
74       published: None,
75       updated: None,
76       actor_id: None,
77       bio: None,
78       local: true,
79       private_key: None,
80       public_key: None,
81       last_refreshed_at: None,
82       inbox_url: None,
83       shared_inbox_url: None,
84     };
85
86     let another_inserted_person = Person::create(&conn, &another_person).unwrap();
87
88     let new_community = CommunityForm {
89       name: "TIL_community_agg".into(),
90       creator_id: inserted_person.id,
91       title: "nada".to_owned(),
92       description: None,
93       nsfw: false,
94       removed: None,
95       deleted: None,
96       updated: None,
97       actor_id: None,
98       local: true,
99       private_key: None,
100       public_key: None,
101       last_refreshed_at: None,
102       published: None,
103       icon: None,
104       banner: None,
105       followers_url: None,
106       inbox_url: None,
107       shared_inbox_url: None,
108     };
109
110     let inserted_community = Community::create(&conn, &new_community).unwrap();
111
112     let new_post = PostForm {
113       name: "A test post".into(),
114       url: None,
115       body: None,
116       creator_id: inserted_person.id,
117       community_id: inserted_community.id,
118       removed: None,
119       deleted: None,
120       locked: None,
121       stickied: None,
122       nsfw: false,
123       updated: None,
124       embed_title: None,
125       embed_description: None,
126       embed_html: None,
127       thumbnail_url: None,
128       ap_id: None,
129       local: true,
130       published: None,
131     };
132
133     let inserted_post = Post::create(&conn, &new_post).unwrap();
134
135     let comment_form = CommentForm {
136       content: "A test comment".into(),
137       creator_id: inserted_person.id,
138       post_id: inserted_post.id,
139       removed: None,
140       deleted: None,
141       read: None,
142       parent_id: None,
143       published: None,
144       updated: None,
145       ap_id: None,
146       local: true,
147     };
148
149     let inserted_comment = Comment::create(&conn, &comment_form).unwrap();
150
151     let child_comment_form = CommentForm {
152       content: "A test comment".into(),
153       creator_id: inserted_person.id,
154       post_id: inserted_post.id,
155       removed: None,
156       deleted: None,
157       read: None,
158       parent_id: Some(inserted_comment.id),
159       published: None,
160       updated: None,
161       ap_id: None,
162       local: true,
163     };
164
165     let _inserted_child_comment = Comment::create(&conn, &child_comment_form).unwrap();
166
167     let post_like = PostLikeForm {
168       post_id: inserted_post.id,
169       person_id: inserted_person.id,
170       score: 1,
171     };
172
173     PostLike::like(&conn, &post_like).unwrap();
174
175     let post_aggs_before_delete = PostAggregates::read(&conn, inserted_post.id).unwrap();
176
177     assert_eq!(2, post_aggs_before_delete.comments);
178     assert_eq!(1, post_aggs_before_delete.score);
179     assert_eq!(1, post_aggs_before_delete.upvotes);
180     assert_eq!(0, post_aggs_before_delete.downvotes);
181
182     // Add a post dislike from the other person
183     let post_dislike = PostLikeForm {
184       post_id: inserted_post.id,
185       person_id: another_inserted_person.id,
186       score: -1,
187     };
188
189     PostLike::like(&conn, &post_dislike).unwrap();
190
191     let post_aggs_after_dislike = PostAggregates::read(&conn, inserted_post.id).unwrap();
192
193     assert_eq!(2, post_aggs_after_dislike.comments);
194     assert_eq!(0, post_aggs_after_dislike.score);
195     assert_eq!(1, post_aggs_after_dislike.upvotes);
196     assert_eq!(1, post_aggs_after_dislike.downvotes);
197
198     // Remove the parent comment
199     Comment::delete(&conn, inserted_comment.id).unwrap();
200     let after_comment_delete = PostAggregates::read(&conn, inserted_post.id).unwrap();
201     assert_eq!(0, after_comment_delete.comments);
202     assert_eq!(0, after_comment_delete.score);
203     assert_eq!(1, after_comment_delete.upvotes);
204     assert_eq!(1, after_comment_delete.downvotes);
205
206     // Remove the first post like
207     PostLike::remove(&conn, inserted_person.id, inserted_post.id).unwrap();
208     let after_like_remove = PostAggregates::read(&conn, inserted_post.id).unwrap();
209     assert_eq!(0, after_like_remove.comments);
210     assert_eq!(-1, after_like_remove.score);
211     assert_eq!(0, after_like_remove.upvotes);
212     assert_eq!(1, after_like_remove.downvotes);
213
214     // This should delete all the associated rows, and fire triggers
215     Person::delete(&conn, another_inserted_person.id).unwrap();
216     let person_num_deleted = Person::delete(&conn, inserted_person.id).unwrap();
217     assert_eq!(1, person_num_deleted);
218
219     // Should be none found, since the creator was deleted
220     let after_delete = PostAggregates::read(&conn, inserted_post.id);
221     assert!(after_delete.is_err());
222   }
223 }