2026-07-18 18:14:29 +03:00
// @ts-check
const { test , expect } = require ( '@playwright/test' );
const fs = require ( 'fs' );
const path = require ( 'path' );
const RESULT_PATH = path . join ( __dirname , '..' , 'test-results' , 'result.json' );
function writeResult ( result ) {
fs . mkdirSync ( path . dirname ( RESULT_PATH ), { recursive : true });
fs . writeFileSync ( RESULT_PATH , JSON . stringify ( result ));
}
test . describe ( 'reddit post' , () => {
let outcome = { success : false , error : 'Test did not complete' };
2026-07-18 18:15:41 +03:00
let outcomeFinalized = false ;
2026-07-18 18:14:29 +03:00
test . afterEach ( async () => {
writeResult ( outcome );
});
test ( 'logs into Reddit and creates a post' , async ({ page }) => {
const username = process . env . REDDIT_USERNAME ;
const password = process . env . REDDIT_PASSWORD ;
const subreddit = process . env . SUBREDDIT ;
const title = process . env . POST_TITLE ;
const body = process . env . POST_BODY ;
for ( const [ name , value ] of Object . entries ({
REDDIT_USERNAME : username ,
REDDIT_PASSWORD : password ,
SUBREDDIT : subreddit ,
POST_TITLE : title ,
POST_BODY : body ,
})) {
if ( ! value ) {
outcome = { success : false , error : `Missing required environment variable: ${ name } ` };
2026-07-18 18:15:41 +03:00
outcomeFinalized = true ;
2026-07-18 18:14:29 +03:00
throw new Error ( outcome . error );
}
}
try {
await page . goto ( 'https://www.reddit.com/login/' );
2026-07-18 18:38:04 +03:00
const blockedHeading = page . getByText ( /blocked by network security/i );
if ( await blockedHeading . isVisible ({ timeout : 3_000 }). catch (() => false )) {
outcome = {
success : false ,
error : 'Reddit blocked this request at the network level ("blocked by network security") before login could be attempted — this is not a credentials or selector issue, it means the current network/IP is being flagged as automation by Reddit' ,
};
outcomeFinalized = true ;
throw new Error ( outcome . error );
}
2026-07-18 18:40:54 +03:00
// Screenshot-verified against the live Reddit login page: cookie
// dialog button text and the "Log In" submit button's accessible
// name are both confirmed correct.
2026-07-18 18:38:04 +03:00
const rejectCookies = page . getByRole ( 'button' , { name : 'Reject Optional Cookies' });
if ( await rejectCookies . isVisible ({ timeout : 5_000 }). catch (() => false )) {
await rejectCookies . click ();
}
2026-07-18 18:40:54 +03:00
// Not individually screenshot-verified (only confirmed to resolve
// as far as the network block allowed) — watch these first if
// login fails on a real, unblocked network.
2026-07-18 18:38:04 +03:00
const usernameField = page . getByLabel ( /email or username/i );
await usernameField . fill ( /** @type {string} */ ( username ));
const passwordField = page . getByLabel ( /^password/i );
await passwordField . fill ( /** @type {string} */ ( password ));
await page . getByRole ( 'button' , { name : 'Log In' }). click ();
2026-07-18 18:14:29 +03:00
try {
await expect ( page . locator ( 'span[name="avatar"], #USER_DROPDOWN_ID, [icon-name="account-circle-outline"]' ). first ()). toBeVisible ({ timeout : 20_000 });
} catch {
2026-07-18 18:38:04 +03:00
const loginErrorBanner = page . getByText ( /something went wrong logging in|invalid username|invalid password/i );
const bannerText = await loginErrorBanner . first (). textContent (). catch (() => null );
2026-07-18 18:14:29 +03:00
outcome = {
success : false ,
2026-07-18 18:38:04 +03:00
error : bannerText
? `Login failed: ${ bannerText . trim () } `
: 'Login did not complete — possible CAPTCHA, 2FA prompt, or invalid credentials' ,
2026-07-18 18:14:29 +03:00
};
2026-07-18 18:15:41 +03:00
outcomeFinalized = true ;
2026-07-18 18:14:29 +03:00
throw new Error ( outcome . error );
}
2026-07-18 18:40:54 +03:00
// UNVERIFIED: a network block in the dev sandbox prevented ever
// reaching this point in a live run, so none of the selectors below
// (text-type tab, title field, body field, submit button) have been
// confirmed against the real submit page. If posting fails here on
// a real, unblocked network, inspect the live page first — e.g. via
// `npx playwright codegen https://www.reddit.com/r/test/submit`.
2026-07-18 18:14:29 +03:00
await page . goto ( `https://www.reddit.com/r/ ${ subreddit } /submit` );
const textTab = page . getByRole ( 'button' , { name : /^Text$/i }). first ();
if ( await textTab . isVisible ({ timeout : 10_000 }). catch (() => false )) {
await textTab . click ();
}
await page . getByPlaceholder ( /title/i ). first (). fill ( /** @type {string} */ ( title ));
const bodyField = page . locator ( '[data-testid="post-composer-rte"], div[role="textbox"]' ). first ();
await bodyField . click ();
await bodyField . fill ( /** @type {string} */ ( body ));
const submitButton = page . getByRole ( 'button' , { name : /^Post$/i }). first ();
await expect ( submitButton ). toBeEnabled ({ timeout : 10_000 });
await submitButton . click ();
try {
await page . waitForURL ( /\/comments\// , { timeout : 20_000 });
} catch {
outcome = { success : false , error : 'Post submission did not complete — no redirect to the new post' };
2026-07-18 18:15:41 +03:00
outcomeFinalized = true ;
2026-07-18 18:14:29 +03:00
throw new Error ( outcome . error );
}
outcome = { success : true , url : page . url () };
2026-07-18 18:15:41 +03:00
outcomeFinalized = true ;
2026-07-18 18:14:29 +03:00
expect ( outcome . success ). toBe ( true );
} catch ( err ) {
2026-07-18 18:15:41 +03:00
if ( ! outcomeFinalized ) {
2026-07-18 18:14:29 +03:00
outcome = { success : false , error : err instanceof Error ? err . message : String ( err ) };
}
throw err ;
}
});
});