Skip to main content

max / multithreaded

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