]> Untitled Git - lemmy.git/blob - crates/db_schema/src/aggregates/comment_aggregates.rs
12b57222805cc23e82484e98085016599d697d95
[lemmy.git] / crates / db_schema / src / aggregates / comment_aggregates.rs
1 use crate::{
2   aggregates::structs::CommentAggregates,
3   newtypes::CommentId,
4   schema::comment_aggregates,
5   utils::{functions::hot_rank, get_conn, DbPool},
6 };
7 use diesel::{result::Error, ExpressionMethods, QueryDsl};
8 use diesel_async::RunQueryDsl;
9
10 impl CommentAggregates {
11   pub async fn read(pool: &mut DbPool<'_>, comment_id: CommentId) -> Result<Self, Error> {
12     let conn = &mut get_conn(pool).await?;
13     comment_aggregates::table
14       .filter(comment_aggregates::comment_id.eq(comment_id))
15       .first::<Self>(conn)
16       .await
17   }
18
19   pub async fn update_hot_rank(
20     pool: &mut DbPool<'_>,
21     comment_id: CommentId,
22   ) -> Result<Self, Error> {
23     let conn = &mut get_conn(pool).await?;
24
25     diesel::update(comment_aggregates::table)
26       .filter(comment_aggregates::comment_id.eq(comment_id))
27       .set(comment_aggregates::hot_rank.eq(hot_rank(
28         comment_aggregates::score,
29         comment_aggregates::published,
30       )))
31       .get_result::<Self>(conn)
32       .await
33   }
34 }
35
36 #[cfg(test)]
37 mod tests {
38   use crate::{
39     aggregates::comment_aggregates::CommentAggregates,
40     source::{
41       comment::{Comment, CommentInsertForm, CommentLike, CommentLikeForm},
42       community::{Community, CommunityInsertForm},
43       instance::Instance,
44       person::{Person, PersonInsertForm},
45       post::{Post, PostInsertForm},
46     },
47     traits::{Crud, Likeable},
48     utils::build_db_pool_for_tests,
49   };
50   use serial_test::serial;
51
52   #[tokio::test]
53   #[serial]
54   async fn test_crud() {
55     let pool = &build_db_pool_for_tests().await;
56     let pool = &mut pool.into();
57
58     let inserted_instance = Instance::read_or_create(pool, "my_domain.tld".to_string())
59       .await
60       .unwrap();
61
62     let new_person = PersonInsertForm::builder()
63       .name("thommy_comment_agg".into())
64       .public_key("pubkey".into())
65       .instance_id(inserted_instance.id)
66       .build();
67
68     let inserted_person = Person::create(pool, &new_person).await.unwrap();
69
70     let another_person = PersonInsertForm::builder()
71       .name("jerry_comment_agg".into())
72       .public_key("pubkey".into())
73       .instance_id(inserted_instance.id)
74       .build();
75
76     let another_inserted_person = Person::create(pool, &another_person).await.unwrap();
77
78     let new_community = CommunityInsertForm::builder()
79       .name("TIL_comment_agg".into())
80       .title("nada".to_owned())
81       .public_key("pubkey".to_string())
82       .instance_id(inserted_instance.id)
83       .build();
84
85     let inserted_community = Community::create(pool, &new_community).await.unwrap();
86
87     let new_post = PostInsertForm::builder()
88       .name("A test post".into())
89       .creator_id(inserted_person.id)
90       .community_id(inserted_community.id)
91       .build();
92
93     let inserted_post = Post::create(pool, &new_post).await.unwrap();
94
95     let comment_form = CommentInsertForm::builder()
96       .content("A test comment".into())
97       .creator_id(inserted_person.id)
98       .post_id(inserted_post.id)
99       .build();
100
101     let inserted_comment = Comment::create(pool, &comment_form, None).await.unwrap();
102
103     let child_comment_form = CommentInsertForm::builder()
104       .content("A test comment".into())
105       .creator_id(inserted_person.id)
106       .post_id(inserted_post.id)
107       .build();
108
109     let _inserted_child_comment =
110       Comment::create(pool, &child_comment_form, Some(&inserted_comment.path))
111         .await
112         .unwrap();
113
114     let comment_like = CommentLikeForm {
115       comment_id: inserted_comment.id,
116       post_id: inserted_post.id,
117       person_id: inserted_person.id,
118       score: 1,
119     };
120
121     CommentLike::like(pool, &comment_like).await.unwrap();
122
123     let comment_aggs_before_delete = CommentAggregates::read(pool, inserted_comment.id)
124       .await
125       .unwrap();
126
127     assert_eq!(1, comment_aggs_before_delete.score);
128     assert_eq!(1, comment_aggs_before_delete.upvotes);
129     assert_eq!(0, comment_aggs_before_delete.downvotes);
130
131     // Add a post dislike from the other person
132     let comment_dislike = CommentLikeForm {
133       comment_id: inserted_comment.id,
134       post_id: inserted_post.id,
135       person_id: another_inserted_person.id,
136       score: -1,
137     };
138
139     CommentLike::like(pool, &comment_dislike).await.unwrap();
140
141     let comment_aggs_after_dislike = CommentAggregates::read(pool, inserted_comment.id)
142       .await
143       .unwrap();
144
145     assert_eq!(0, comment_aggs_after_dislike.score);
146     assert_eq!(1, comment_aggs_after_dislike.upvotes);
147     assert_eq!(1, comment_aggs_after_dislike.downvotes);
148
149     // Remove the first comment like
150     CommentLike::remove(pool, inserted_person.id, inserted_comment.id)
151       .await
152       .unwrap();
153     let after_like_remove = CommentAggregates::read(pool, inserted_comment.id)
154       .await
155       .unwrap();
156     assert_eq!(-1, after_like_remove.score);
157     assert_eq!(0, after_like_remove.upvotes);
158     assert_eq!(1, after_like_remove.downvotes);
159
160     // Remove the parent post
161     Post::delete(pool, inserted_post.id).await.unwrap();
162
163     // Should be none found, since the post was deleted
164     let after_delete = CommentAggregates::read(pool, inserted_comment.id).await;
165     assert!(after_delete.is_err());
166
167     // This should delete all the associated rows, and fire triggers
168     Person::delete(pool, another_inserted_person.id)
169       .await
170       .unwrap();
171     let person_num_deleted = Person::delete(pool, inserted_person.id).await.unwrap();
172     assert_eq!(1, person_num_deleted);
173
174     // Delete the community
175     let community_num_deleted = Community::delete(pool, inserted_community.id)
176       .await
177       .unwrap();
178     assert_eq!(1, community_num_deleted);
179
180     Instance::delete(pool, inserted_instance.id).await.unwrap();
181   }
182 }