← back to Newmor Onboard
scripts/verify-live-pages.py
69 lines
import datetime, hashlib, json, pathlib, re, sys, time, urllib.parse, urllib.request, urllib.error
from html.parser import HTMLParser
ROOT=pathlib.Path('/Users/macstudio3/Projects/newmor-onboard')
class Element:
def __init__(self,tag,attrs): self.tag=tag; self.attrs=dict(attrs); self.parts=[]
def text(self): return ''.join(x.text() if isinstance(x,Element) else x for x in self.parts)
def has(self,cls): return cls in self.attrs.get('class','').split()
class Document(HTMLParser):
def __init__(self,html):
super().__init__(convert_charrefs=True); self.root=Element('document',[]); self.stack=[self.root]; self.nodes=[]; self.feed(html)
def handle_starttag(self,tag,attrs):
n=Element(tag,attrs); self.stack[-1].parts.append(n); self.nodes.append(n)
if tag not in {'area','base','br','col','embed','hr','img','input','link','meta','param','source','track','wbr'}: self.stack.append(n)
def handle_startendtag(self,tag,attrs): self.handle_starttag(tag,attrs); self.handle_endtag(tag)
def handle_endtag(self,tag):
for i in range(len(self.stack)-1,0,-1):
if self.stack[i].tag==tag: self.stack=self.stack[:i]; break
def handle_data(self,data): self.stack[-1].parts.append(data)
def read(name): return json.loads((ROOT/name).read_text())
def fetch(url):
for attempt in range(4):
try:
with urllib.request.urlopen(urllib.request.Request(url,headers={'User-Agent':'Mozilla/5.0 Newmor showroom verification'}),timeout=60) as response:
return response.status,response.read().decode(),response.url
except urllib.error.HTTPError as e:
if e.code in [429,430] and attempt<3: time.sleep(15); continue
return e.code,e.read().decode(errors='replace'),e.url
raise AssertionError('Rate limit persisted')
results=[]
try:
snapshot=read('data/live-2026-09-09/shopify-before.json')['products']
journal=read('data/live-2026-09-09/product-launch-journal.json')['records']
live=[r for r in journal if r.get('after',{}).get('status')=='ACTIVE']
for r in live:
p=r['after']; url='https://www.designerwallcoverings.com/products/'+p['handle']
status,html,final=fetch(url); assert status==200,(r['code'],status)
doc=Document(html); nodes=doc.nodes
assert not any(n.has('product__price') or n.has('product-add-to-cart') for n in nodes),(r['code'],'material purchase UI')
assert any(n.has('dw-quote-badge-title') and n.text().strip()=='Newmor Showroom Line' for n in nodes)
assert any(n.has('dw-sample-button') and re.search(r'Sample.*\$4\.25',n.text(),re.S) for n in nodes)
assert any(n.tag=='form' and n.attrs.get('id')=='dw-quote-form' for n in nodes)
assert any(n.attrs.get('id')=='dw-q-product-id' and n.attrs.get('value')==p['id'].split('/')[-1] for n in nodes)
assert any(n.tag=='a' and n.attrs.get('href')=='tel:+18883734564' for n in nodes)
mails=[urllib.parse.parse_qs(urllib.parse.urlsplit(n.attrs['href']).query).get('subject',[]) for n in nodes if n.tag=='a' and n.attrs.get('href','').startswith('mailto:info@designerwallcoverings.com')]
sku=p['variants']['nodes'][0]['sku']; assert ['Newmor inquiry: '+sku] in mails,(r['code'],'SKU inquiry')
metadata=[]
for n in nodes:
if n.tag=='script' and n.attrs.get('type')=='application/ld+json':
try: metadata.append(json.loads(n.text()))
except json.JSONDecodeError: pass
products=[m for m in metadata if isinstance(m,dict) and m.get('@type')=='Product'];assert products and all('offers' not in m for m in products)
results.append({'id':p['id'],'code':r['code'],'http':status,'html_sha256':hashlib.sha256(html.encode()).hexdigest(),'no_material_price_or_buy':True,'sample_label':True,'sku_contact':True,'quote_form':True,'no_material_offer_metadata':True})
print('PASS public',r['code'],flush=True);time.sleep(.25)
range_holds={c['id'] for c in read('data/live-2026-09-09/vendor-range.json')['candidates'] if not c['found']}
held=read('data/newmor-showroom-plan-2026-09-08.json')['held'];held_ids={p['id'] for p in held[:3]}
archive_ids={p['id'] for p in snapshot if p['status']=='ARCHIVED'};archive_ids=set(sorted(archive_ids)[:3])
negatives=[]
for p in snapshot:
if p['id'] not in range_holds|held_ids|archive_ids: continue
status,html,final=fetch('https://www.designerwallcoverings.com/products/'+p['handle']);assert status==404,(p['id'],'held product exposed',status)
negatives.append({'id':p['id'],'http':status,'expected':'held/archive remains unavailable'})
proof={'timestamp':datetime.datetime.now(datetime.timezone.utc).isoformat(),'verdict':'PASS','live_count':len(live),'results':results,'negative_probes':negatives,'limitations':['Raw HTML verifies every published product; interactive Chromium/WebKit canary proves the shared inquiry/cart behavior.','No quote email, authenticated checkout or order submitted.']}
(ROOT/'verification/public-pages-proof.json').write_text(json.dumps(proof,indent=2)+'\n');print('PASS all',len(live),'live pages and',len(negatives),'held/archive404probes')
except Exception as e:
(ROOT/'verification/public-pages-proof.json').write_text(json.dumps({'timestamp':datetime.datetime.now(datetime.timezone.utc).isoformat(),'verdict':'FAIL','error':repr(e),'results':results},indent=2)+'\n');raise