Files
ScadaBridge/infra/tools/inspect_states_and_utc.py
T
2026-11-13 18:23:12 -05:00

21 lines
3.6 KiB
Python

"""Bounded local actual-component state/UTC check; never submits a backend write."""
from pathlib import Path
import json
from playwright.sync_api import sync_playwright
out=Path('docs/ui-consistency/evidence/sb04-06/browser-confirmation');out.mkdir(parents=True,exist_ok=True);results=[]
with sync_playwright() as p:
browser=p.chromium.launch(channel='chromium')
for width in [1440,390]:
for zone in ['America/New_York','Asia/Tokyo']:
page=browser.new_page(viewport={'width':width,'height':1000},timezone_id=zone,reduced_motion='reduce');page.goto('http://127.0.0.1:5201/batch-two?sample=audit',wait_until='networkidle');page.select_option('#audit-time-range','Custom');page.fill('#audit-from','2026-03-08T01:30');page.fill('#audit-to','2026-03-08T02:30');page.click('[data-test=filter-apply]');page.wait_for_function('document.querySelector("#local-filter-result").textContent.includes("FromKind=Utc")');text=page.locator('#local-filter-result').inner_text();record={'sample':'audit','width':width,'browserZone':zone,'utcResult':text,'checks':{'literalUTC':'From=2026-03-08T01:30:00.0000000Z' in text and 'To=2026-03-08T02:30:00.0000000Z' in text}}
page.fill('#audit-from','2026-03-08T03:30');page.click('[data-test=filter-apply]');page.locator('#audit-range-error').wait_for();record['checks']['invertedBlocked']=page.locator('#local-filter-result').inner_text()==text and page.get_attribute('#audit-from','aria-invalid')=='true';record['errorColor']=page.locator('#audit-range-error').evaluate('e=>getComputedStyle(e).color');record['checks']['correctionPreserved']=page.input_value('#audit-from')=='2026-03-08T03:30';page.screenshot(path=str(out/f'audit-{zone.split("/")[-1]}-{width}.png'),full_page=True);results.append(record);page.close()
for sample in ['dashboard','toast']:
page=browser.new_page(viewport={'width':width,'height':1000},reduced_motion='reduce');page.goto('http://127.0.0.1:5201/batch-two?sample='+sample,wait_until='networkidle');record={'sample':sample,'width':width,'checks':{}}
if sample=='dashboard':
fact=page.locator('[role=region][aria-label="API keys"]');record['checks']['unavailableNotZero']='Unavailable' in fact.inner_text();page.get_by_role('button',name='Retry API keys',exact=True).click();page.wait_for_function('selector=>{const text=document.querySelector(selector).textContent;return !text.includes("Unavailable")&&!text.includes("Loading");}',arg='[role=region][aria-label="API keys"]');record['checks']['retryKnownZero']='0' in fact.inner_text() and 'Unavailable' not in fact.inner_text();record['checks']['otherFactsRemain']=all('0' in page.locator('[role=region][aria-label="'+label+'"]').inner_text() for label in ['Sites configured','Data connections configured','Templates'])
else:
page.click('#show-toast');page.get_by_role('button',name='Dismiss Local configuration',exact=True).click();page.wait_for_function('document.querySelectorAll(".toast").length===1');record['checks']['onlyTargetDismissed']=page.locator('.toast').count()==1 and 'Local audit query' in page.locator('.toast').inner_text();record['checks']['otherDismissNamed']=page.get_by_role('button',name='Dismiss Local audit query',exact=True).count()==1
record['layout']=page.evaluate('({innerWidth,scrollWidth:document.documentElement.scrollWidth})');page.screenshot(path=str(out/f'{sample}-{width}.png'),full_page=True);results.append(record);page.close()
browser.close()
(out/'results.json').write_text(json.dumps({'results':results,'passed':all(all(r['checks'].values()) for r in results)},indent=2)+'\n');print([(r['sample'],r['width'],all(r['checks'].values())) for r in results])