← back to Newmor Onboard

scripts/canary-journey.cjs

103 lines

const fs=require('node:fs');const assert=require('node:assert/strict');
const {chromium,webkit}=require('/Users/macstudio3/.npm-global/lib/node_modules/playwright');
const root='/Users/macstudio3/Projects/newmor-onboard';
const ids=['4351291785267','4351291818035'];
const snap=JSON.parse(fs.readFileSync(root+'/data/live-2026-09-09/shopify-before.json')).products;
const {backgroundOwner,sanitize}=require('./browser-errors.cjs');
const backgroundError=e=>!!backgroundOwner(e);
const previous=process.argv.includes('--resume')?JSON.parse(fs.readFileSync(root+'/verification/canary-proof.json')).results:[];
const results=[...new Map(previous.map(r=>[r.engine+':'+(r.id||r.boundary),r])).values()];
for(const r of results)if(r.page_errors)r.page_errors=r.page_errors.map(sanitize);
async function cartJSON(context,path,method='get'){
 for(let attempt=0;attempt<5;attempt++){
  const r=await context.request[method]('https://www.designerwallcoverings.com'+path,method==='post'?{data:{}}:{});
  if([429,430].includes(r.status())){console.log(`Cart rate limit ${r.status()}; bounded backoff ${attempt+1}`);await new Promise(r=>setTimeout(r,15000));continue;}
  assert.equal(r.status(),200,`Cart ${path} HTTP ${r.status()}`);
  if(!/json|javascript/.test(r.headers()['content-type']||'')){const u=new URL(r.url());const html=await r.text();throw Error(`Cart ${path} returned ${r.headers()['content-type']} at ${u.origin+u.pathname}; title=${html.match(/<title[^>]*>([^<]*)/i)?.[1]}; h1=${html.match(/<h1[^>]*>([^<]*)/i)?.[1]}`);}return r.json();
 }
 throw Error('Cart rate limit persists');
}
(async()=>{
 for(const [engineName,engine] of [['chromium',chromium],['webkit',webkit]]){
  const browser=await engine.launch();
  try{
   for(const mobile of [false,true]){
    const name=engineName+(mobile?'-mobile':'-desktop');
    if(process.argv.includes('--resume')&&results.filter(r=>r.engine===name&&r.product_http===200).length===2&&results.some(r=>r.engine===name&&r.cart_cleanup&&r.page_errors.every(backgroundError))){console.log(`Retain verified ${name} journey; recorded analytics sandbox exceptions are nonblocking`);continue;}
    for(let i=results.length-1;i>=0;i--)if(results[i].engine===name)results.splice(i,1);
    const context=await browser.newContext({viewport:mobile?{width:390,height:844}:{width:1440,height:1000},recordVideo:{dir:root+'/verification/canary/'+name}});
    try{
     const page=await context.newPage();const errors=[];page.on('pageerror',e=>errors.push(sanitize(e.stack)));
     for(const id of ids){
      const p=snap.find(p=>p.id.endsWith('/'+id));const sku=p.variants.nodes[0].sku;
      const url='https://www.designerwallcoverings.com/products/'+p.handle;
      const response=await page.goto(url,{waitUntil:'domcontentloaded',timeout:60000});assert.equal(response.status(),200);
      await page.waitForTimeout(engineName==='webkit'?7000:3500);
      const decline=page.getByRole('button',{name:'Decline',exact:true});if(await decline.isVisible().catch(()=>false))await decline.click({timeout:5000});
      assert(await page.getByText('Newmor Showroom Line',{exact:true}).isVisible());
      assert.equal(await page.locator('.product__price').count(),0,'Material price row present');
      assert.equal(await page.locator('.product-add-to-cart').count(),0,'Material purchase control present');
      assert(await page.locator('.dw-sample-button').isVisible());assert.match(await page.locator('.dw-sample-button').innerText(),/Sample.*\$4\.25/);
      const meta=await page.locator('script[type="application/ld+json"]').evaluateAll(nodes=>nodes.map(n=>{try{return JSON.parse(n.textContent)}catch{return null}}).filter(Boolean));
      const productMeta=meta.find(x=>x['@type']==='Product');assert(productMeta);assert(!productMeta.offers,'Sample price still attributed to material');
      const email=await page.getByRole('link',{name:'Email about this colorway',exact:true}).getAttribute('href');
      assert.equal(new URL(email).searchParams.get('subject'),'Newmor inquiry: '+sku);
      assert.equal(await page.getByRole('link',{name:'Call the showroom',exact:true}).getAttribute('href'),'tel:+18883734564');
      await page.locator('.dw-quote-section').scrollIntoViewIfNeeded();
      await page.screenshot({path:root+`/verification/canary/${name}/${id}-product.png`,fullPage:true});
      await page.getByRole('button',{name:'Request a Quote',exact:true}).click();
      assert(await page.locator('#dw-quote-modal.active').isVisible());
      assert.equal(await page.locator('#dw-q-product-id').inputValue(),id);
      await page.locator('#dw-quote-form button[type="submit"]').click();
      assert.equal(await page.locator('#dw-quote-form').evaluate(f=>f.checkValidity()),false);
      await page.screenshot({path:root+`/verification/canary/${name}/${id}-inquiry.png`,fullPage:true});
      await page.keyboard.press('Escape');assert.equal(await page.locator('#dw-quote-modal.active').count(),0);
      await page.getByRole('button',{name:'Request a Quote',exact:true}).click();await page.locator('.dw-quote-modal-close').click();assert.equal(await page.locator('#dw-quote-modal.active').count(),0);
      results.push({engine:name,id,product_http:response.status(),no_material_price:true,no_material_buy:true,no_product_offer:true,sample_label:true,phone_href:true,sku_email_href:true,quote_open_close:true,empty_form_rejected:true});
     }
     // Exercise the actual public sample/cart boundary in a disposable anonymous session.
     const p=snap.find(p=>p.id.endsWith('/'+ids[1]));
     await page.locator('.dw-sample-button').click();await page.waitForURL(/\/cart/,{timeout:20000});
     const cart=await cartJSON(context,'/cart.js');
     assert.equal(cart.items.length,1);assert.equal(String(cart.items[0].variant_id),p.variants.nodes[0].id.split('/').at(-1));assert.equal(cart.items[0].variant_title,'Sample');
     assert.match(await page.locator('body').innerText(),/Sample/);
     await page.screenshot({path:root+`/verification/canary/${name}/sample-cart.png`,fullPage:true});
     let checkoutStatus=null,authBoundary=false;
     if(name==='chromium-desktop'){
     let checkout;
     for(let attempt=0;attempt<3;attempt++){
      checkout=await page.goto('https://www.designerwallcoverings.com/checkout',{waitUntil:'domcontentloaded',timeout:60000});await page.waitForTimeout(3000);
      if(![429,430].includes(checkout.status()))break;
      console.log(`Checkout rate limit ${checkout.status()}; bounded30second backoff`);await page.waitForTimeout(30000);
     }
     const summary=page.getByRole('button',{name:/Show order summary/i});if(await summary.isVisible().catch(()=>false))await summary.click();
     const checkoutText=await page.locator('body').innerText();
     const checkoutUrl=new URL(page.url());
     authBoundary=checkoutUrl.hostname==='shopify.com'&&/^\/authentication\/\d+\/login\/?$/.test(checkoutUrl.pathname);
     fs.writeFileSync(root+`/verification/canary/${name}/checkout-state.json`,JSON.stringify({url:checkoutUrl.origin+checkoutUrl.pathname,status:checkout.status(),text:checkoutText,anonymous_auth_boundary:authBoundary},null,2)+'\n');
     await page.screenshot({path:root+`/verification/canary/${name}/sample-checkout.png`,fullPage:true});
     assert.equal(checkout.status(),200);
     if(authBoundary){assert.match(checkoutText,/Sign in/);assert(await page.getByRole('textbox',{name:'Email',exact:true}).isVisible());}
     else assert(/Sample/i.test(checkoutText),'Checkout does not identify Sample');
     checkoutStatus=checkout.status();
     }
     await cartJSON(context,'/cart/clear.js','post');
     assert.equal((await cartJSON(context,'/cart.js')).item_count,0);
     results.push({engine:name,boundary:'cart-checkout',sample_cart_identity:true,anonymous_auth_boundary:authBoundary,authenticated_checkout:'UNTESTED',checkout_http:checkoutStatus,redundant_auth_navigation:name==='chromium-desktop'?'EXERCISED':'SKIP: shared auth endpoint verified in Chromium desktop; repeated auth requests previously rate limited',cart_cleanup:true,page_errors:errors,nonblocking_external_errors:errors.filter(backgroundError).map(e=>({owner:backgroundOwner(e),error:e}))});
     const critical=errors.filter(e=>!backgroundError(e));
     assert.equal(critical.length,0,critical.join('\n'));
     console.log(`PASS ${name}:2PDPs,inquiry,Sample cart,${authBoundary?'checkout sign-in boundary,':''}cleanup`);
    }finally{await cartJSON(context,'/cart/clear.js','post').catch(e=>console.error('Cleanup failed:',e.message));await context.close();}
   }
  }finally{await browser.close();}
 }
 assert(results.some(r=>r.anonymous_auth_boundary&&r.checkout_http===200),'Shared checkout auth boundary not verified');
 for(const name of ['chromium-desktop','chromium-mobile','webkit-desktop','webkit-mobile']){
  assert.equal(results.filter(r=>r.engine===name&&r.product_http===200).length,2);
  const cart=results.find(r=>r.engine===name&&r.cart_cleanup);assert(cart&&cart.sample_cart_identity&&cart.page_errors.every(backgroundError));
  cart.nonblocking_external_errors=cart.page_errors.filter(backgroundError).map(e=>({owner:backgroundOwner(e),error:e}));
 }
 const proof={timestamp:new Date().toISOString(),ids:ids.map(x=>'gid://shopify/Product/'+x),verdict:'PASS',results,limitations:['Recorded Statcounter and Meta pixel sandbox exceptions are nonblocking external analytics errors; no analytics repair claimed.','No quote email submitted;phone/email handoff and browser validation exercised.','Anonymous checkout reaches Shopify sign-in in Chromium desktop; redundant auth navigations skipped after observed429. Authenticated checkout and order submission untested.','Browserbase cloud not used;local Chromium and WebKit desktop/mobile exercised.','Global navigation/footer controls unchanged and outside this scoped launch click-list.']};
 fs.writeFileSync(root+'/verification/canary-proof.json',JSON.stringify(proof,null,2)+'\n');
})().catch(e=>{fs.mkdirSync(root+'/verification',{recursive:true});fs.writeFileSync(root+'/verification/canary-proof.json',JSON.stringify({timestamp:new Date().toISOString(),ids:ids.map(x=>'gid://shopify/Product/'+x),verdict:'FAIL',error:e.message,results},null,2)+'\n');console.error(e.stack);process.exit(1)});