Skip to main content

max / makenotwork

9.8 KB · 314 lines History Blame Raw
1 use crate::harness::TestHarness;
2
3 #[tokio::test]
4 async fn mention_renders_as_profile_link() {
5 let mut h = TestHarness::new().await;
6 let author_id = h.login_as("mentionauth").await;
7 let comm_id = h.create_community("Test", "test").await;
8 let _cat_id = h.create_category(comm_id, "General", "general").await;
9 h.add_membership(author_id, comm_id, "member").await;
10
11 // Create the mentioned user via direct SQL (so author stays logged in)
12 let mentioned_id = uuid::Uuid::new_v4();
13 sqlx::query("INSERT INTO users (mnw_account_id, username, display_name) VALUES ($1, $2, $2)")
14 .bind(mentioned_id)
15 .bind("mentionee")
16 .execute(&h.db)
17 .await
18 .unwrap();
19 h.add_membership(mentioned_id, comm_id, "member").await;
20
21 // GET page for CSRF
22 h.client.get("/p/test/general/new").await;
23
24 // Create thread via HTTP with @mention
25 let resp = h
26 .client
27 .post_form(
28 "/p/test/general/new",
29 "title=Mention+Test&body=Hello+%40mentionee+welcome",
30 )
31 .await;
32 assert!(
33 resp.status.is_redirection(),
34 "Expected redirect, got {}",
35 resp.status
36 );
37
38 // Find the thread and view it
39 let threads =
40 mt_db::queries::list_threads_in_category_paginated(&h.db, "test", "general", 10, 0)
41 .await
42 .unwrap();
43 assert!(!threads.is_empty());
44 let thread_id = threads[0].id;
45
46 let thread_url = format!("/p/test/general/{thread_id}");
47 let resp = h.client.get(&thread_url).await;
48
49 assert!(
50 resp.text.contains("/p/test/u/mentionee"),
51 "Expected mention to render as profile link. Body: {}",
52 &resp.text[resp.text.find("post-body").unwrap_or(0)..]
53 .chars()
54 .take(500)
55 .collect::<String>()
56 );
57 }
58
59 #[tokio::test]
60 async fn mention_stored_in_db() {
61 let mut h = TestHarness::new().await;
62 let author_id = h.login_as("mentiondbauth").await;
63 let comm_id = h.create_community("Test", "test").await;
64 let _cat_id = h.create_category(comm_id, "General", "general").await;
65 h.add_membership(author_id, comm_id, "member").await;
66
67 // Create mentioned user via direct SQL
68 let mentioned_id = uuid::Uuid::new_v4();
69 sqlx::query("INSERT INTO users (mnw_account_id, username, display_name) VALUES ($1, $2, $2)")
70 .bind(mentioned_id)
71 .bind("mentiondbuser")
72 .execute(&h.db)
73 .await
74 .unwrap();
75 h.add_membership(mentioned_id, comm_id, "member").await;
76
77 h.client.get("/p/test/general/new").await;
78 h.client
79 .post_form(
80 "/p/test/general/new",
81 "title=DB+Test&body=Hey+%40mentiondbuser",
82 )
83 .await;
84
85 // Check DB for mention row
86 let threads =
87 mt_db::queries::list_threads_in_category_paginated(&h.db, "test", "general", 10, 0)
88 .await
89 .unwrap();
90 let thread_id = threads[0].id;
91 let posts = mt_db::queries::list_posts_in_thread(&h.db, thread_id)
92 .await
93 .unwrap();
94 let post_id = posts[0].id;
95
96 let count: i64 = sqlx::query_scalar(
97 "SELECT COUNT(*) FROM post_mentions WHERE post_id = $1 AND mentioned_user_id = $2",
98 )
99 .bind(post_id)
100 .bind(mentioned_id)
101 .fetch_one(&h.db)
102 .await
103 .unwrap();
104
105 assert_eq!(count, 1, "Expected 1 mention row in DB");
106 }
107
108 #[tokio::test]
109 async fn self_mention_not_stored() {
110 let mut h = TestHarness::new().await;
111 let author_id = h.login_as("selfmentioner").await;
112 let comm_id = h.create_community("Test", "test").await;
113 let _cat_id = h.create_category(comm_id, "General", "general").await;
114 h.add_membership(author_id, comm_id, "member").await;
115
116 h.client.get("/p/test/general/new").await;
117 h.client
118 .post_form(
119 "/p/test/general/new",
120 "title=Self+Mention&body=I+am+%40selfmentioner",
121 )
122 .await;
123
124 let threads =
125 mt_db::queries::list_threads_in_category_paginated(&h.db, "test", "general", 10, 0)
126 .await
127 .unwrap();
128 let thread_id = threads[0].id;
129 let posts = mt_db::queries::list_posts_in_thread(&h.db, thread_id)
130 .await
131 .unwrap();
132 let post_id = posts[0].id;
133
134 let count: i64 = sqlx::query_scalar("SELECT COUNT(*) FROM post_mentions WHERE post_id = $1")
135 .bind(post_id)
136 .fetch_one(&h.db)
137 .await
138 .unwrap();
139
140 assert_eq!(count, 0, "Self-mention should not be stored in DB");
141 }
142
143 #[tokio::test]
144 async fn unknown_username_left_as_text() {
145 let mut h = TestHarness::new().await;
146 let author_id = h.login_as("unknownmentionauth").await;
147 let comm_id = h.create_community("Test", "test").await;
148 let _cat_id = h.create_category(comm_id, "General", "general").await;
149 h.add_membership(author_id, comm_id, "member").await;
150
151 h.client.get("/p/test/general/new").await;
152 h.client
153 .post_form(
154 "/p/test/general/new",
155 "title=Unknown+Mention&body=Hello+%40nonexistent",
156 )
157 .await;
158
159 let threads =
160 mt_db::queries::list_threads_in_category_paginated(&h.db, "test", "general", 10, 0)
161 .await
162 .unwrap();
163 let thread_id = threads[0].id;
164
165 let thread_url = format!("/p/test/general/{thread_id}");
166 let resp = h.client.get(&thread_url).await;
167
168 // Should contain @nonexistent as plain text, not as a link
169 assert!(
170 resp.text.contains("@nonexistent"),
171 "Unknown mention should appear as plain text"
172 );
173 assert!(
174 !resp.text.contains("/p/test/u/nonexistent"),
175 "Unknown mention should NOT be a link"
176 );
177
178 // No DB rows
179 let posts = mt_db::queries::list_posts_in_thread(&h.db, thread_id)
180 .await
181 .unwrap();
182 let post_id = posts[0].id;
183 let count: i64 = sqlx::query_scalar("SELECT COUNT(*) FROM post_mentions WHERE post_id = $1")
184 .bind(post_id)
185 .fetch_one(&h.db)
186 .await
187 .unwrap();
188 assert_eq!(count, 0, "No mention rows for unknown username");
189 }
190
191 #[tokio::test]
192 async fn mention_indicator_on_category_listing() {
193 let mut h = TestHarness::new().await;
194 let author_id = h.login_as("catmentionauth").await;
195 let comm_id = h.create_community("Test", "test").await;
196 let _cat_id = h.create_category(comm_id, "General", "general").await;
197 h.add_membership(author_id, comm_id, "member").await;
198
199 // Create the mentioned user via direct SQL
200 let mentioned_id = uuid::Uuid::new_v4();
201 sqlx::query("INSERT INTO users (mnw_account_id, username, display_name) VALUES ($1, $2, $2)")
202 .bind(mentioned_id)
203 .bind("catmentionee")
204 .execute(&h.db)
205 .await
206 .unwrap();
207 h.add_membership(mentioned_id, comm_id, "member").await;
208
209 // Author creates thread mentioning the other user
210 h.client.get("/p/test/general/new").await;
211 let resp = h
212 .client
213 .post_form(
214 "/p/test/general/new",
215 "title=Category+Mention+Test&body=Hey+%40catmentionee+check+this",
216 )
217 .await;
218 assert!(
219 resp.status.is_redirection(),
220 "Expected redirect, got {}",
221 resp.status
222 );
223
224 // Re-login as the mentioned user and view the category
225 h.client.get("/").await;
226 let body = serde_json::json!({
227 "user_id": mentioned_id.to_string(),
228 "username": "catmentionee",
229 });
230 h.client.post_json("/_test/login", &body.to_string()).await;
231
232 let resp = h.client.get("/p/test/general").await;
233 assert!(
234 resp.text.contains("badge-mention"),
235 "Expected badge-mention class in category listing. Body snippet: {}",
236 &resp.text[resp.text.find("data-table").unwrap_or(0)..]
237 .chars()
238 .take(800)
239 .collect::<String>()
240 );
241 assert!(
242 resp.text.contains("mentioned"),
243 "Expected 'mentioned' class on tr element"
244 );
245 }
246
247 #[tokio::test]
248 async fn mention_indicator_on_tracked_page() {
249 let mut h = TestHarness::new().await;
250 let author_id = h.login_as("trackmentionauth").await;
251 let comm_id = h.create_community("Test", "test").await;
252 let _cat_id = h.create_category(comm_id, "General", "general").await;
253 h.add_membership(author_id, comm_id, "member").await;
254
255 // Create the mentioned user
256 let mentioned_id = uuid::Uuid::new_v4();
257 sqlx::query("INSERT INTO users (mnw_account_id, username, display_name) VALUES ($1, $2, $2)")
258 .bind(mentioned_id)
259 .bind("trackmentionee")
260 .execute(&h.db)
261 .await
262 .unwrap();
263 h.add_membership(mentioned_id, comm_id, "member").await;
264
265 // Author creates thread mentioning user B
266 h.client.get("/p/test/general/new").await;
267 let resp = h
268 .client
269 .post_form(
270 "/p/test/general/new",
271 "title=Track+Mention+Test&body=Hello+%40trackmentionee",
272 )
273 .await;
274 assert!(
275 resp.status.is_redirection(),
276 "Expected redirect, got {}",
277 resp.status
278 );
279
280 // Find thread ID
281 let threads =
282 mt_db::queries::list_threads_in_category_paginated(&h.db, "test", "general", 10, 0)
283 .await
284 .unwrap();
285 let thread_id = threads[0].id;
286
287 // User B tracks the thread
288 mt_db::mutations::track_thread(&h.db, mentioned_id, thread_id)
289 .await
290 .unwrap();
291
292 // Log in as mentioned user
293 let body = serde_json::json!({
294 "user_id": mentioned_id.to_string(),
295 "username": "trackmentionee",
296 });
297 h.client.post_json("/_test/login", &body.to_string()).await;
298
299 // View tracked page
300 let resp = h.client.get("/tracked").await;
301 assert!(
302 resp.text.contains("badge-mention"),
303 "Expected badge-mention in tracked page. Body snippet: {}",
304 &resp.text[resp.text.find("data-table").unwrap_or(0)..]
305 .chars()
306 .take(800)
307 .collect::<String>()
308 );
309 assert!(
310 resp.text.contains("mentioned"),
311 "Expected 'mentioned' class on tr element in tracked page"
312 );
313 }
314