/** * e2e-paypal-portal-fix.mjs - verify that completing a compliance order (the * path PayPal/Stripe/crypto all funnel through) creates the Postgres `customers` * row, so the customer can log in / reset password. Regression test for the * Paul Wilson PayPal login bug (2026-06-09). * * It seeds a fake pending compliance order, calls the compiled * handlePaymentComplete(), then asserts a customers row now exists. Cleans up. * * Run: docker exec performancewest-api-1 node /app/scripts/e2e-paypal-portal-fix.mjs */ import pg from "pg"; const pool = new pg.Pool({ connectionString: process.env.DATABASE_URL }); const { handlePaymentComplete } = await import("/app/dist/routes/checkout.js"); const EMAIL = `e2e-portal+${Date.now().toString().slice(-7)}@example-e2e.test`; const ORDER = `CO-E2E${Date.now().toString().slice(-6)}`; let fail = 0; const ok = (m) => console.log(" [PASS] " + m); const bad = (m) => { console.log(" [FAIL] " + m); fail++; }; try { // 1) seed a pending compliance order (admin-assisted D&A, no intake gating needed for this test) await pool.query( `INSERT INTO compliance_orders (order_number, service_slug, service_name, customer_name, customer_email, payment_method, payment_status, service_fee_cents, intake_data) VALUES ($1,'dot-drug-alcohol','DOT Drug & Alcohol Compliance Program', 'E2E Tester','${EMAIL}','paypal','pending_payment',14900, '{"company":"E2E Co"}'::jsonb)`, [ORDER], ); ok(`seeded pending compliance order ${ORDER}`); // precondition: no customers row yet const before = await pool.query(`SELECT id FROM customers WHERE email=$1`, [EMAIL]); if (before.rows.length === 0) ok("precondition: no customers row before payment"); else bad("precondition failed: customers row already existed"); // 2) simulate payment completion (the PayPal/Stripe/crypto common path) await handlePaymentComplete(ORDER, "compliance", "e2e-test-session"); ok("handlePaymentComplete ran"); // 3) assert: order marked paid + customers row created const ord = await pool.query(`SELECT payment_status FROM compliance_orders WHERE order_number=$1`, [ORDER]); if (ord.rows[0]?.payment_status === "paid") ok("order marked paid"); else bad(`order not paid (got ${ord.rows[0]?.payment_status})`); const after = await pool.query(`SELECT id, name, company, password_hash FROM customers WHERE email=$1`, [EMAIL]); if (after.rows.length === 1) { ok(`customers row created (id=${after.rows[0].id}, name=${after.rows[0].name}, company=${after.rows[0].company})`); if (after.rows[0].password_hash === null) ok("customers row has no password (correct: customer sets it via register/reset)"); else bad("customers row unexpectedly has a password_hash"); } else { bad("customers row was NOT created (the bug would still be present)"); } } catch (e) { bad("exception: " + e.message); } finally { // cleanup await pool.query(`DELETE FROM password_reset_tokens WHERE customer_id IN (SELECT id FROM customers WHERE email=$1)`, [EMAIL]).catch(()=>{}); await pool.query(`DELETE FROM customers WHERE email=$1`, [EMAIL]).catch(()=>{}); await pool.query(`DELETE FROM compliance_orders WHERE order_number=$1`, [ORDER]).catch(()=>{}); console.log(" cleaned up test order + customers row"); await pool.end(); } console.log(fail === 0 ? "\n=== ALL CHECKS PASSED ===" : `\n=== ${fail} CHECK(S) FAILED ===`); process.exit(fail === 0 ? 0 : 1);