Skip to main content

max / makenotwork

6.8 KB · 208 lines History Blame Raw
1 use crate::harness::TestHarness;
2
3 #[tokio::test]
4 async fn profile_page_shows_user_info() {
5 let mut h = TestHarness::new().await;
6 let user_id = h.login_as("profileuser").await;
7 let comm_id = h.create_community("TestCommunity", "test-comm").await;
8 h.create_category(comm_id, "General", "general").await;
9 h.add_membership(user_id, comm_id, "member").await;
10
11 let resp = h.client.get("/p/test-comm/u/profileuser").await;
12 assert_eq!(resp.status.as_u16(), 200, "profile page should load");
13 assert!(resp.text.contains("profileuser"), "should show username");
14 assert!(resp.text.contains("member"), "should show role badge");
15 assert!(resp.text.contains("Joined"), "should show join date");
16 }
17
18 #[tokio::test]
19 async fn profile_page_shows_activity() {
20 let mut h = TestHarness::new().await;
21 let user_id = h.login_as("activeuser").await;
22 let comm_id = h.create_community("ActivityComm", "activity-comm").await;
23 let cat_id = h.create_category(comm_id, "General", "general").await;
24 h.add_membership(user_id, comm_id, "member").await;
25
26 // Create a thread (user is thread author)
27 let thread_id = h
28 .create_thread_with_post(cat_id, user_id, "My Thread", "Hello world")
29 .await;
30
31 // Create a reply in another thread
32 let thread_id_2 = h
33 .create_thread_with_post(cat_id, user_id, "Another Thread", "Second post")
34 .await;
35 mt_db::mutations::create_post(
36 &h.db,
37 thread_id_2,
38 user_id,
39 "A reply",
40 "<p>A reply</p>",
41 true,
42 )
43 .await
44 .unwrap();
45
46 let resp = h.client.get("/p/activity-comm/u/activeuser").await;
47 assert_eq!(resp.status.as_u16(), 200);
48 assert!(resp.text.contains("My Thread"), "should list thread activity");
49 assert!(resp.text.contains("Another Thread"), "should list reply activity");
50
51 // Verify thread_id link is present
52 assert!(
53 resp.text.contains(&thread_id.to_string()),
54 "should link to thread"
55 );
56 }
57
58 #[tokio::test]
59 async fn profile_nonmember_returns_404() {
60 let mut h = TestHarness::new().await;
61 h.login_as("outsider").await;
62 let _comm_id = h.create_community("ClosedComm", "closed-comm").await;
63
64 // User exists but is not a member
65 let resp = h.client.get("/p/closed-comm/u/outsider").await;
66 assert_eq!(resp.status.as_u16(), 404, "non-member should get 404");
67 }
68
69 #[tokio::test]
70 async fn profile_nonexistent_user_404() {
71 let mut h = TestHarness::new().await;
72 h.login_as("someuser").await;
73 let _comm_id = h.create_community("SomeComm", "some-comm").await;
74
75 let resp = h.client.get("/p/some-comm/u/nobodyhere").await;
76 assert_eq!(resp.status.as_u16(), 404, "nonexistent user should get 404");
77 }
78
79 #[tokio::test]
80 async fn profile_suspended_community_blocked() {
81 let mut h = TestHarness::new().await;
82 let user_id = h.login_as("suspendedfan").await;
83 let comm_id = h.create_community("SuspendedComm", "suspended-comm").await;
84 h.add_membership(user_id, comm_id, "member").await;
85
86 // Suspend the community
87 sqlx::query("UPDATE communities SET suspended_at = now() WHERE id = $1")
88 .bind(comm_id)
89 .execute(&h.db)
90 .await
91 .unwrap();
92
93 let resp = h.client.get("/p/suspended-comm/u/suspendedfan").await;
94 assert_eq!(
95 resp.status.as_u16(),
96 403,
97 "suspended community should return 403"
98 );
99 }
100
101 #[tokio::test]
102 async fn api_summary_requires_auth() {
103 let mut h = TestHarness::new().await;
104 // Don't log in — make unauthenticated request
105 h.client.get("/").await; // establish session
106
107 let user_id = uuid::Uuid::new_v4();
108 let resp = h
109 .client
110 .get(&format!("/api/user/{}/summary", user_id))
111 .await;
112 assert_eq!(resp.status.as_u16(), 401, "unauthenticated should get 401");
113 }
114
115 #[tokio::test]
116 async fn api_summary_returns_memberships() {
117 let mut h = TestHarness::new().await;
118 let user_id = h.login_as("summaryuser").await;
119 let comm_id = h.create_community("SummaryComm", "summary-comm").await;
120 h.add_membership(user_id, comm_id, "member").await;
121
122 let resp = h
123 .client
124 .get(&format!("/api/user/{}/summary", user_id))
125 .await;
126 assert_eq!(resp.status.as_u16(), 200, "should return 200");
127
128 let json: serde_json::Value = resp.json();
129 let memberships = json["memberships"].as_array().unwrap();
130 assert_eq!(memberships.len(), 1, "should have one membership");
131 assert_eq!(memberships[0]["community_name"], "SummaryComm");
132 assert_eq!(memberships[0]["community_slug"], "summary-comm");
133 assert_eq!(memberships[0]["role"], "member");
134 }
135
136 #[tokio::test]
137 async fn api_summary_only_own_data() {
138 let mut h = TestHarness::new().await;
139 let _user_id = h.login_as("snoop").await;
140
141 // Try to access another user's summary
142 let other_id = uuid::Uuid::new_v4();
143 let resp = h
144 .client
145 .get(&format!("/api/user/{}/summary", other_id))
146 .await;
147 assert_eq!(
148 resp.status.as_u16(),
149 403,
150 "accessing other user's data should return 403"
151 );
152 }
153
154 #[tokio::test]
155 async fn profile_shows_endorsement_count() {
156 let mut h = TestHarness::new().await;
157 let author_id = h.login_as("endorsedauthor").await;
158 let comm_id = h.create_community("EndorseComm", "endorse-comm").await;
159 let cat_id = h.create_category(comm_id, "General", "general").await;
160 h.add_membership(author_id, comm_id, "member").await;
161
162 // Author creates a thread with a post
163 let thread_id = h
164 .create_thread_with_post(cat_id, author_id, "Great Thread", "Great content")
165 .await;
166
167 // Get the first post ID
168 let posts = mt_db::queries::list_posts_in_thread(&h.db, thread_id).await.unwrap();
169 let post_id = posts[0].id;
170
171 // Another user endorses the post
172 let endorser_id = h.login_as("endorser1").await;
173 h.add_membership(endorser_id, comm_id, "member").await;
174 mt_db::mutations::toggle_endorsement(&h.db, post_id, endorser_id)
175 .await
176 .unwrap();
177
178 // Check the author's profile shows endorsement count
179 let resp = h.client.get("/p/endorse-comm/u/endorsedauthor").await;
180 assert_eq!(resp.status.as_u16(), 200);
181 assert!(
182 resp.text.contains("1 endorsement received"),
183 "Profile should show endorsement count. Body: {}",
184 &resp.text[..500.min(resp.text.len())]
185 );
186 }
187
188 #[tokio::test]
189 async fn tracking_info_page_loads() {
190 let mut h = TestHarness::new().await;
191 h.login_as("infouser").await;
192
193 let resp = h.client.get("/about/tracking").await;
194 assert_eq!(resp.status.as_u16(), 200);
195 assert!(
196 resp.text.contains("How Tracking Works"),
197 "Should show tracking info heading"
198 );
199 assert!(
200 resp.text.contains("localStorage"),
201 "Should explain localStorage tracking"
202 );
203 assert!(
204 resp.text.contains("No third-party"),
205 "Should mention no third-party tracking"
206 );
207 }
208