@@ -193,4 +193,100 @@ test.describe("Posting", () => {
193193 // Verify the new thread appears in the listing
194194 await expect ( page . locator ( "body" ) ) . toContainText ( testSubject ) ;
195195 } ) ;
196+
197+ test ( "hard spam detection triggers CAPTCHA challenge" , async ( { page } ) => {
198+ const timestamp = Date . now ( ) ;
199+ // "hardspamtest" in subject triggers certainlySpam (1.0) response
200+ const testSubject = `hardspamtest ${ timestamp } ` ;
201+ const testBody = `Testing hard spam moderation flow ${ timestamp } ` ;
202+
203+ await page . goto ( "/newpost/test" ) ;
204+
205+ // Fill in the form with hard spam-triggering subject
206+ await page . fill ( "#postform-name" , "Test User" ) ;
207+ await page . fill ( "#postform-email" , "test@example.com" ) ;
208+ await page . fill ( "#postform-subject" , testSubject ) ;
209+ await page . fill ( "#postform-text" , testBody ) ;
210+
211+ // Submit the form
212+ await page . click ( 'input[name="action-send"]' ) ;
213+
214+ // Should be challenged with CAPTCHA (dummy checkbox)
215+ const captchaCheckbox = page . locator ( 'input[name="dummy_captcha_checkbox"]' ) ;
216+ await expect ( captchaCheckbox ) . toBeVisible ( ) ;
217+
218+ // Should show "I am not a robot" text
219+ await expect ( page . locator ( "body" ) ) . toContainText ( "I am not a robot" ) ;
220+ } ) ;
221+
222+ test ( "hard spam post is quarantined after solving CAPTCHA" , async ( {
223+ page,
224+ } ) => {
225+ const timestamp = Date . now ( ) ;
226+ // "hardspamtest" in subject triggers certainlySpam (1.0) response
227+ const testSubject = `hardspamtest moderated ${ timestamp } ` ;
228+ const testBody = `Testing hard spam quarantine ${ timestamp } ` ;
229+
230+ await page . goto ( "/newpost/test" ) ;
231+
232+ // Fill in the form with hard spam-triggering subject
233+ await page . fill ( "#postform-name" , "Test User" ) ;
234+ await page . fill ( "#postform-email" , "test@example.com" ) ;
235+ await page . fill ( "#postform-subject" , testSubject ) ;
236+ await page . fill ( "#postform-text" , testBody ) ;
237+
238+ // Submit the form - should trigger CAPTCHA
239+ await page . click ( 'input[name="action-send"]' ) ;
240+
241+ // Wait for CAPTCHA checkbox to appear
242+ const captchaCheckbox = page . locator ( 'input[name="dummy_captcha_checkbox"]' ) ;
243+ await expect ( captchaCheckbox ) . toBeVisible ( ) ;
244+
245+ // Check the CAPTCHA checkbox
246+ await captchaCheckbox . check ( ) ;
247+
248+ // Submit again with CAPTCHA solved
249+ await page . click ( 'input[name="action-send"]' ) ;
250+
251+ // Should NOT redirect to thread - should show moderation message
252+ // The URL should stay on posting page (not redirect to thread)
253+ await expect ( page ) . not . toHaveURL ( / \/ ( t h r e a d | p o s t ) \/ / ) ;
254+
255+ // Should show moderation message
256+ await expect ( page . locator ( "body" ) ) . toContainText (
257+ "approved by a moderator"
258+ ) ;
259+ } ) ;
260+
261+ test ( "quarantined post does not appear in group listing" , async ( { page } ) => {
262+ const timestamp = Date . now ( ) ;
263+ const testSubject = `hardspamtest hidden ${ timestamp } ` ;
264+ const testBody = `This post should be hidden ${ timestamp } ` ;
265+
266+ await page . goto ( "/newpost/test" ) ;
267+
268+ // Fill in and submit with hard spam-triggering subject
269+ await page . fill ( "#postform-name" , "Test User" ) ;
270+ await page . fill ( "#postform-email" , "test@example.com" ) ;
271+ await page . fill ( "#postform-subject" , testSubject ) ;
272+ await page . fill ( "#postform-text" , testBody ) ;
273+ await page . click ( 'input[name="action-send"]' ) ;
274+
275+ // Solve CAPTCHA
276+ const captchaCheckbox = page . locator ( 'input[name="dummy_captcha_checkbox"]' ) ;
277+ await expect ( captchaCheckbox ) . toBeVisible ( ) ;
278+ await captchaCheckbox . check ( ) ;
279+ await page . click ( 'input[name="action-send"]' ) ;
280+
281+ // Should show moderation message
282+ await expect ( page . locator ( "body" ) ) . toContainText (
283+ "approved by a moderator"
284+ ) ;
285+
286+ // Navigate to group listing
287+ await page . goto ( "/group/test" ) ;
288+
289+ // Verify the quarantined thread does NOT appear in the listing
290+ await expect ( page . locator ( "body" ) ) . not . toContainText ( testSubject ) ;
291+ } ) ;
196292} ) ;
0 commit comments