← back to Dw Signup Fulfillment
verification/shopify-account-e2e.js
208 lines
'use strict';
const fs = require('fs');
const path = require('path');
const { execFileSync } = require('child_process');
const { chromium } = require(path.join(
process.env.HOME,
'Projects/Designer-Wallcoverings/node_modules/playwright'
));
const shopify = require('../lib/shopify');
const STOREFRONT = 'https://www.designerwallcoverings.com/pages/trade-only-benefits';
const SAMPLE_VARIANT_ID = 13960778743920;
const artifacts = path.join(__dirname, 'artifacts');
fs.mkdirSync(artifacts, { recursive: true });
function check(condition, message) {
if (!condition) throw new Error(message);
}
function remoteGeorge(endpoint) {
const source = `
const config = require('./lib/config');
const auth = 'Basic ' + Buffer.from(config.GEORGE_BASIC_AUTH).toString('base64');
fetch('http://127.0.0.1:9850' + Buffer.from(process.argv[1], 'base64').toString(), {
headers: { authorization: auth }
}).then(async response => {
const body = await response.text();
if (!response.ok) throw new Error(response.status + ' ' + body);
process.stdout.write(body);
}).catch(error => { console.error(error.message); process.exit(1); });
`;
const encodedSource = Buffer.from(source).toString('base64');
const encodedEndpoint = Buffer.from(endpoint).toString('base64');
const command = `cd /root/Projects/dw-signup-fulfillment && node -e "eval(Buffer.from('${encodedSource}','base64').toString())" '${encodedEndpoint}'`;
return JSON.parse(execFileSync('ssh', [
'-o', 'BatchMode=yes',
'-o', 'ConnectTimeout=12',
'root@45.61.58.125',
command,
], { encoding: 'utf8', timeout: 30000 }));
}
async function waitForLoginCode(email, notBefore) {
const query = `to:${email} newer_than:1d`;
const deadline = Date.now() + 120000;
while (Date.now() < deadline) {
const search = remoteGeorge(`/api/search?account=steve-office&maxResults=10&q=${encodeURIComponent(query)}`);
for (const item of search.messages || []) {
const message = remoteGeorge(`/api/messages/${encodeURIComponent(item.id)}?account=steve-office`);
if (Number(message.internalDate || 0) < notBefore - 30000) continue;
const haystack = `${message.subject || ''}\n${message.snippet || ''}\n${message.body || ''}`;
const code = haystack.match(/(?:code|verification)[^0-9]{0,80}([0-9]{6})/i)?.[1]
|| haystack.match(/\b([0-9]{6})\b/)?.[1];
if (code) return code;
}
await new Promise(resolve => setTimeout(resolve, 3000));
}
throw new Error('Shopify login code did not arrive in the controlled mailbox within 120 seconds');
}
async function waitForShopifyCustomer(email) {
const deadline = Date.now() + 90000;
while (Date.now() < deadline) {
const customerId = await shopify.findCustomerByEmail(email);
if (customerId) return customerId;
await new Promise(resolve => setTimeout(resolve, 5000));
}
return null;
}
async function main() {
const runId = new Date().toISOString().replace(/[:.]/g, '-');
const mode = process.env.DW_ACCOUNT_E2E_MODE === 'designer' ? 'designer' : 'retail';
const email = process.env.DW_ACCOUNT_E2E_EMAIL
|| (mode === 'designer'
? 'steve+dw-e2e-designer@designerwallcoverings.com'
: 'steve+dw-e2e-shopify@designerwallcoverings.com');
const evidence = {
intent: 'Prove a new controlled customer can enter Shopify email-code authentication and return to DW authenticated',
environment: 'production controlled canary',
timestamp: new Date().toISOString(),
syntheticAccount: email,
accountMode: mode,
checks: [],
artifacts: [],
};
const pass = (name, detail) => evidence.checks.push({ name, verdict: 'PASS', detail });
const browser = await chromium.launch({
headless: true,
executablePath: '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
});
const context = await browser.newContext({ viewport: { width: 1440, height: 1000 } });
const page = await context.newPage();
try {
await page.goto(`${STOREFRONT}?account_e2e=${encodeURIComponent(runId)}`, { waitUntil: 'load', timeout: 45000 });
await page.locator('[data-dw-returning]').first().click();
const authHref = await page.locator('#dwReturningDialog a.dw-ta-button').getAttribute('href');
check(authHref && /customer_authentication\/redirect/.test(authHref), 'DW secure sign-in handoff is missing');
pass('DW handoff', 'Returning-client action opens the branded reassurance dialog and supplies Shopify secure authentication');
const sentAt = Date.now();
await page.goto(authHref, { waitUntil: 'domcontentloaded', timeout: 45000 });
const emailInput = page.locator('input[type="email"], input[autocomplete="email"]').first();
await emailInput.waitFor({ state: 'visible', timeout: 30000 });
await emailInput.fill(email);
const beforeCode = path.join(artifacts, `shopify-account-email-${runId}.png`);
await page.screenshot({ path: beforeCode, fullPage: true });
evidence.artifacts.push(beforeCode);
const continueButton = page.getByRole('button', { name: /continue|submit|sign in/i }).last();
await continueButton.click();
pass('account entry', 'A unique DW-owned synthetic email was accepted by Shopify customer authentication');
const code = await waitForLoginCode(email, sentAt);
const codeInputs = page.locator('input[inputmode="numeric"], input[autocomplete="one-time-code"]');
await codeInputs.first().waitFor({ state: 'visible', timeout: 30000 });
const count = await codeInputs.count();
if (count === 1) {
await codeInputs.first().fill(code);
} else {
for (let i = 0; i < Math.min(count, code.length); i += 1) await codeInputs.nth(i).fill(code[i]);
}
const verifyButton = page.getByRole('button', { name: /continue|submit|verify|sign in/i });
if (await verifyButton.count()) await verifyButton.last().click();
await page.waitForURL(url => !url.hostname.endsWith('shopify.com') || /account/.test(url.pathname), { timeout: 45000 });
await page.waitForLoadState('domcontentloaded');
pass('email-code verification', 'The Shopify one-time code arrived in the controlled DW mailbox and was accepted');
const finalUrl = page.url();
check(
/shopify\.com\/1541177456\/account/.test(finalUrl) || /designerwallcoverings\.com/.test(finalUrl),
`authentication did not reach the store's authenticated account surface: ${finalUrl}`
);
const accountText = await page.locator('body').innerText();
check(/account|orders|profile|sign out/i.test(accountText), 'authenticated account controls were not visible');
const afterAuth = path.join(artifacts, `shopify-account-authenticated-${runId}.png`);
await page.screenshot({ path: afterAuth, fullPage: true });
evidence.artifacts.push(afterAuth);
pass('authenticated account', `Shopify opened the store's authenticated customer-account surface at ${new URL(finalUrl).origin}`);
if (mode === 'designer') {
const customerId = await waitForShopifyCustomer(email);
check(customerId, 'controlled designer customer could not be resolved through Shopify Admin API');
const tagged = await shopify.addTags(customerId, ['trade_approved']);
check(tagged?.ok && !tagged?.dryRun, 'controlled designer account was not tagged trade_approved in production');
evidence.syntheticCustomerId = String(customerId);
pass('designer approval', 'The DW-owned synthetic customer received the exact authoritative trade_approved entitlement tag');
}
await page.goto(STOREFRONT, { waitUntil: 'load', timeout: 45000 });
const accountLinks = page.locator('a[href*="/account"], a[href*="customer_authentication"]');
check(await accountLinks.count() > 0, 'DW storefront no longer exposes an account route after authentication');
pass('storefront return', 'The authenticated browser returned to DW and retained an accessible customer-account route');
const cartResult = await page.evaluate(async variantId => {
await fetch('/cart/clear.js', { method: 'POST', headers: { accept: 'application/json' } });
const response = await fetch('/cart/add.js', {
method: 'POST',
headers: { 'content-type': 'application/json', accept: 'application/json' },
body: JSON.stringify({ items: [{ id: variantId, quantity: 4 }] }),
});
return { status: response.status, body: await response.json() };
}, SAMPLE_VARIANT_ID);
check(cartResult.status === 200, `sample cart add returned ${cartResult.status}`);
check(cartResult.body?.items?.[0]?.quantity === 4, 'sample cart did not retain quantity four');
pass('sample cart', mode === 'designer'
? 'Four $4.25 sample units were added to the controlled approved-designer cart to test unlimited sample entitlement'
: 'Four $4.25 sample units were added to the controlled retail cart to test the three-lifetime limit');
await page.goto('https://www.designerwallcoverings.com/checkout', { waitUntil: 'domcontentloaded', timeout: 60000 });
await page.waitForTimeout(8000);
const checkoutText = (await page.locator('body').innerText()).replace(/\s+/g, ' ');
const checkoutShot = path.join(artifacts, `shopify-account-checkout-${runId}.png`);
await page.screenshot({ path: checkoutShot, fullPage: true });
evidence.artifacts.push(checkoutShot);
check(/free samples|discount/i.test(checkoutText), 'free-sample discount was not visible at checkout');
if (mode === 'designer') {
check(/\$17\.00/.test(checkoutText), 'approved designer checkout did not show all four samples discounted by $17.00');
check(/(?:USD\s*)?\$0\.00/.test(checkoutText), 'approved designer checkout total was not $0.00 before shipping');
pass('designer checkout boundary', 'At production checkout, an approved designer receives all four sample units free ($17.00 off); no order was submitted');
} else {
check(/\$12\.75/.test(checkoutText), 'checkout did not show the expected three-sample $12.75 discount');
check(/\$4\.25/.test(checkoutText), 'checkout did not retain one paid $4.25 sample after the three free units');
pass('retail checkout boundary', 'At production checkout, four samples receive exactly $12.75 off and retain one paid $4.25 unit; no order was submitted');
}
await page.goto('https://www.designerwallcoverings.com/cart/clear', { waitUntil: 'domcontentloaded', timeout: 30000 });
evidence.verdict = 'PASS';
evidence.retainedState = mode === 'designer'
? 'Synthetic DW-owned account retained with trade_approved for repeatable designer checkout validation; no real customer record was changed.'
: 'Synthetic DW-owned retail account retained for repeatable checkout/sample validation; no real customer record was changed.';
const report = path.join(__dirname, `shopify-account-${mode}-e2e.json`);
fs.writeFileSync(report, `${JSON.stringify(evidence, null, 2)}\n`);
console.log(JSON.stringify({ ok: true, email, checks: evidence.checks.length, finalUrl, report }, null, 2));
} finally {
await browser.close();
}
}
main().catch(error => {
console.error(`SHOPIFY ACCOUNT E2E FAILED: ${error.stack || error.message}`);
process.exit(1);
});