← back to Dw Signup Fulfillment

verification/tk11120/prove-real-customer.js

71 lines

'use strict';
// TK-11120 — end-to-end proof that a REAL customer clicking the corrected verify link is
// confirmed with ZERO user input. Creates a throwaway Shopify customer, hits the LIVE
// /verify HTTP endpoint with a real token, asserts "Email confirmed" + the verified-sample
// tag lands, then DELETES the throwaway customer. Reversible + self-cleaning.
const http = require('http');
const https = require('https');
const config = require('./../../lib/config');
const verify = require('./../../lib/verify');

const SHOP = config.SHOP_DOMAIN, VER = config.SHOPIFY_API_VERSION, TOK = config.SHOPIFY_FULFILLMENT_TOKEN;
function shopify(method, path, body) {
  return new Promise((resolve) => {
    const data = body ? JSON.stringify(body) : null;
    const req = https.request({ hostname: SHOP, path: `/admin/api/${VER}/${path}`, method,
      headers: { 'X-Shopify-Access-Token': TOK, 'Content-Type': 'application/json', ...(data ? { 'Content-Length': Buffer.byteLength(data) } : {}) } },
      res => { let d = ''; res.on('data', c => d += c); res.on('end', () => { let j = null; try { j = JSON.parse(d); } catch {} resolve({ status: res.statusCode, json: j }); }); });
    req.on('error', e => resolve({ status: 0, error: e.message })); if (data) req.write(data); req.end();
  });
}
const PUBLIC = (process.env.PUBLIC_URL || 'https://signup.designerwallcoverings.com').replace(/\/+$/, '');
function getVerify(path) {
  return new Promise((resolve) => { https.get(PUBLIC + path, res => { let d = ''; res.on('data', c => d += c); res.on('end', () => resolve({ status: res.statusCode, body: d })); }).on('error', e => resolve({ status: 0, error: e.message })); });
}

const argv = process.argv.slice(2);
const SETUP = argv.includes('--setup');           // create + print ID/URL, do NOT click or delete
const DELID = argv.includes('--delete') ? argv[argv.indexOf('--delete') + 1] : null; // delete a customer by id

(async () => {
  if (DELID) { const d = await shopify('DELETE', `customers/${DELID}.json`); console.log('deleted id=', DELID, '→ status', d.status); process.exit(d.status === 200 ? 0 : 1); }
  if (SETUP) {
    const email = argv.find(a => a.includes('@')) || `steve+tk11120-show-${Date.now()}@designerwallcoverings.com`;
    const c = await shopify('POST', 'customers.json', { customer: { email, first_name: 'Steve', verified_email: true } });
    const cust = c.json && c.json.customer;
    if (!cust || !cust.id) { console.log('CREATE FAILED', c.status, JSON.stringify(c.json)); process.exit(1); }
    const token = verify.mintToken({ email, customerId: String(cust.id) });
    console.log('ID=' + cust.id);
    console.log('URL=' + PUBLIC + '/verify?token=' + encodeURIComponent(token));
    process.exit(0);
  }
  const email = `steve+tk11120-realcust-${Date.now()}@designerwallcoverings.com`;
  console.log('1) creating throwaway Shopify customer:', email);
  const c = await shopify('POST', 'customers.json', { customer: { email, first_name: 'RealTest', verified_email: true } });
  const cust = c.json && c.json.customer;
  if (!cust || !cust.id) { console.log('   CREATE FAILED', c.status, JSON.stringify(c.json)); process.exit(1); }
  const id = cust.id; console.log('   created id=', id);
  let pass = false, tags = '';
  try {
    const token = verify.mintToken({ email, customerId: String(id) });
    console.log('2) clicking /verify (no sign-in, no form) ...');
    const r = await getVerify(`/verify?token=${encodeURIComponent(token)}`);
    const confirmed = /Email confirmed/i.test(r.body);
    const attachFail = /couldn.t attach/i.test(r.body);
    const h1 = (r.body.match(/<h1[^>]*>([^<]*)<\/h1>/) || [])[1] || '';
    const msg = (r.body.match(/<p style="color:#4b5563[^"]*">([^<]*)<\/p>/) || [])[1] || '';
    console.log('   HTTP', r.status, '| H1:', JSON.stringify(h1), '| MSG:', JSON.stringify(msg).slice(0, 160));
    console.log('   "Email confirmed":', confirmed, '| "couldn\'t attach":', attachFail);
    const g = await shopify('GET', `customers/${id}.json`);
    tags = (g.json && g.json.customer && g.json.customer.tags) || '';
    const tagged = tags.toLowerCase().includes(config.VERIFIED_TAG.toLowerCase());
    console.log('3) customer tags now:', JSON.stringify(tags), '| has', config.VERIFIED_TAG + ':', tagged);
    pass = confirmed && tagged && !attachFail;
  } finally {
    const d = await shopify('DELETE', `customers/${id}.json`);
    console.log('4) deleted throwaway customer id=', id, '→ status', d.status);
  }
  console.log(pass ? '\n✅ PASS — real customer click confirms + tags, zero user input.' : '\n❌ FAIL — see above.');
  process.exit(pass ? 0 : 1);
})().catch(e => { console.error('ERR', e.message); process.exit(1); });