]> Untitled Git - lemmy.git/blob - crates/db_queries/src/aggregates/post_aggregates.rs
2fcb6f5d2132b8782d914cf94560c9566b1bbca2
[lemmy.git] / crates / db_queries / src / aggregates / post_aggregates.rs
1 use diesel::{result::Error, *};
2 use lemmy_db_schema::{schema::post_aggregates, PostId};
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: PostId,
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: PostId) -> 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     Likeable,
35   };
36   use lemmy_db_schema::source::{
37     comment::{Comment, CommentForm},
38     community::{Community, CommunityForm},
39     person::{Person, PersonForm},
40     post::{Post, PostForm, PostLike, PostLikeForm},
41   };
42   use serial_test::serial;
43
44   #[test]
45   #[serial]
46   fn test_crud() {
47     let conn = establish_unpooled_connection();
48
49     let new_person = PersonForm {
50       name: "thommy_community_agg".into(),
51       ..PersonForm::default()
52     };
53
54     let inserted_person = Person::create(&conn, &new_person).unwrap();
55
56     let another_person = PersonForm {
57       name: "jerry_community_agg".into(),
58       ..PersonForm::default()
59     };
60
61     let another_inserted_person = Person::create(&conn, &another_person).unwrap();
62
63     let new_community = CommunityForm {
64       name: "TIL_community_agg".into(),
65       title: "nada".to_owned(),
66       ..CommunityForm::default()
67     };
68
69     let inserted_community = Community::create(&conn, &new_community).unwrap();
70
71     let new_post = PostForm {
72       name: "A test post".into(),
73       creator_id: inserted_person.id,
74       community_id: inserted_community.id,
75       ..PostForm::default()
76     };
77
78     let inserted_post = Post::create(&conn, &new_post).unwrap();
79
80     let comment_form = CommentForm {
81       content: "A test comment".into(),
82       creator_id: inserted_person.id,
83       post_id: inserted_post.id,
84       ..CommentForm::default()
85     };
86
87     let inserted_comment = Comment::create(&conn, &comment_form).unwrap();
88
89     let child_comment_form = CommentForm {
90       content: "A test comment".into(),
91       creator_id: inserted_person.id,
92       post_id: inserted_post.id,
93       parent_id: Some(inserted_comment.id),
94       ..CommentForm::default()
95     };
96
97     let _inserted_child_comment = Comment::create(&conn, &child_comment_form).unwrap();
98
99     let post_like = PostLikeForm {
100       post_id: inserted_post.id,
101       person_id: inserted_person.id,
102       score: 1,
103     };
104
105     PostLike::like(&conn, &post_like).unwrap();
106
107     let post_aggs_before_delete = PostAggregates::read(&conn, inserted_post.id).unwrap();
108
109     assert_eq!(2, post_aggs_before_delete.comments);
110     assert_eq!(1, post_aggs_before_delete.score);
111     assert_eq!(1, post_aggs_before_delete.upvotes);
112     assert_eq!(0, post_aggs_before_delete.downvotes);
113
114     // Add a post dislike from the other person
115     let post_dislike = PostLikeForm {
116       post_id: inserted_post.id,
117       person_id: another_inserted_person.id,
118       score: -1,
119     };
120
121     PostLike::like(&conn, &post_dislike).unwrap();
122
123     let post_aggs_after_dislike = PostAggregates::read(&conn, inserted_post.id).unwrap();
124
125     assert_eq!(2, post_aggs_after_dislike.comments);
126     assert_eq!(0, post_aggs_after_dislike.score);
127     assert_eq!(1, post_aggs_after_dislike.upvotes);
128     assert_eq!(1, post_aggs_after_dislike.downvotes);
129
130     // Remove the parent comment
131     Comment::delete(&conn, inserted_comment.id).unwrap();
132     let after_comment_delete = PostAggregates::read(&conn, inserted_post.id).unwrap();
133     assert_eq!(0, after_comment_delete.comments);
134     assert_eq!(0, after_comment_delete.score);
135     assert_eq!(1, after_comment_delete.upvotes);
136     assert_eq!(1, after_comment_delete.downvotes);
137
138     // Remove the first post like
139     PostLike::remove(&conn, inserted_person.id, inserted_post.id).unwrap();
140     let after_like_remove = PostAggregates::read(&conn, inserted_post.id).unwrap();
141     assert_eq!(0, after_like_remove.comments);
142     assert_eq!(-1, after_like_remove.score);
143     assert_eq!(0, after_like_remove.upvotes);
144     assert_eq!(1, after_like_remove.downvotes);
145
146     // This should delete all the associated rows, and fire triggers
147     Person::delete(&conn, another_inserted_person.id).unwrap();
148     let person_num_deleted = Person::delete(&conn, inserted_person.id).unwrap();
149     assert_eq!(1, person_num_deleted);
150
151     // Delete the community
152     let community_num_deleted = Community::delete(&conn, inserted_community.id).unwrap();
153     assert_eq!(1, community_num_deleted);
154
155     // Should be none found, since the creator was deleted
156     let after_delete = PostAggregates::read(&conn, inserted_post.id);
157     assert!(after_delete.is_err());
158   }
159 }