ouroboros / source /scripts /check_atlas_refresh.py
REXWind's picture
Publish the Ouroboros scientific showcase to CladeTeam
03677d0 verified
Raw History Blame Contribute Delete
7.83 kB
"""Browser regression for the paper Atlas refresh; uses real full-corpus lookup.
Run against the built server with a pinned Atlas release. Set CHROMIUM_PATH and
PREVIEW_URL for local installations. No live inference jobs are submitted.
"""
import json
import os
from pathlib import Path
from playwright.sync_api import sync_playwright, expect
ROOT = Path(__file__).resolve().parents[1]
OUT = ROOT/'artifacts/atlas-refresh-20261110'
BASE = os.environ.get('PREVIEW_URL','http://127.0.0.1:7860')
CASES = json.loads((ROOT/'public/data/atlas-cases.json').read_text())
POINTS = json.loads((ROOT/'public/data/atlas-map.json').read_text())
checks=[]
def passed(message):
checks.append(message)
print(message,flush=True)
with sync_playwright() as p:
browser=p.chromium.launch(executable_path=os.environ.get('CHROMIUM_PATH'),args=['--no-sandbox','--disable-dev-shm-usage','--use-gl=angle','--use-angle=swiftshader','--enable-unsafe-swiftshader'])
context=browser.new_context(viewport={'width':1440,'height':1050},device_scale_factor=1)
page=context.new_page();errors=[];requests=[]
page.on('pageerror',lambda e:errors.append(str(e)))
page.on('request',lambda r:requests.append(r.url))
page.goto(BASE+'/atlas',wait_until='domcontentloaded')
expect(page.locator('.atlas-marker')).to_have_count(8)
assert page.locator('.atlas-map-error').count()==0
expect(page.locator('.atlas-case')).to_have_count(8)
boxes=page.locator('.atlas-marker').evaluate_all('(els)=>els.map(e=>{let r=e.getBoundingClientRect();return {x:r.x,y:r.y,w:r.width,h:r.height}})')
for i,a in enumerate(boxes):
for b in boxes[i+1:]:
assert a['x']+a['w']<=b['x'] or b['x']+b['w']<=a['x'] or a['y']+a['h']<=b['y'] or b['y']+b['h']<=a['y'], 'Overlapping case markers'
page.wait_for_timeout(750)
page.screenshot(path=str(OUT/'final-atlas.png'),full_page=True)
passed('Eight separated paper landmarks render on the real WebGL map')
for i,c in enumerate(CASES):
page.locator('.atlas-case').nth(i).click()
expect(page.locator('.atlas-detail-body h2')).to_have_text(c['uniref_id'])
page.locator('.atlas-structure .molecule[data-render-state="ready"]').wait_for(timeout=30000)
expect(page.locator('.atlas-marker.selected')).to_have_count(1)
passed('All eight case cards, structures and selected map locations work')
page.get_by_role('button',name='Next showcase',exact=True).click()
expect(page.locator('.atlas-detail-body h2')).to_have_text(CASES[0]['uniref_id'])
page.reload(wait_until='domcontentloaded')
expect(page.locator('.atlas-detail-body h2')).to_have_text(CASES[0]['uniref_id'])
page.get_by_role('button',name='Next showcase',exact=True).click();page.go_back()
expect(page.locator('.atlas-detail-body h2')).to_have_text(CASES[0]['uniref_id'])
passed('Case next/previous navigation, deep links, refresh and browser history preserve selection')
page.get_by_role('button',name='pLDDT confidence',exact=True).click()
expect(page.get_by_role('button',name='pLDDT confidence',exact=True)).to_have_attribute('aria-pressed','true')
page.get_by_role('button',name='N → C terminus',exact=True).click()
page.get_by_role('button',name='Swiss-Prot overlap',exact=True).click()
expect(page.get_by_role('button',name='Swiss-Prot overlap',exact=True)).to_have_attribute('aria-pressed','true')
page.get_by_role('button',name='Sequence communities',exact=True).click()
page.get_by_role('button',name='Reset map',exact=True).click()
expect(page.locator('.atlas-marker')).to_have_count(8)
page.get_by_role('button',name='Zoom in',exact=True).click();page.get_by_role('button',name='Zoom out',exact=True).click()
canvas=page.locator('.atlas-map canvas');canvas.focus();page.keyboard.press('ArrowLeft');page.keyboard.press('0')
page.wait_for_timeout(600);page.locator('.atlas-workspace').screenshot(path=str(OUT/'final-atlas-selected.png'))
passed('Coverage layer, structure coloring, zoom/reset and keyboard pan work')
outside='UniRef50_A0A418SD25';assert outside not in POINTS['ids']
field=page.get_by_role('textbox',name='Find an Atlas record by ID')
field.fill(outside[9:].lower());page.get_by_role('button',name='Find protein',exact=False).click()
expect(page.locator('.atlas-detail-body h2')).to_have_text(outside,timeout=60000)
expect(page.locator('.atlas-location')).to_contain_text('outside the current map sample')
passed('Real full-corpus lookup resolves a protein absent from the 12,000-point sample')
field.fill('../bad');page.get_by_role('button',name='Find protein',exact=False).click()
expect(page.locator('.atlas-error')).to_contain_text('Enter a record ID')
page.locator('.atlas-case').nth(0).click()
with page.expect_download() as download:
page.get_by_role('button',name='↓ FASTA',exact=True).click()
assert download.value.suggested_filename.endswith('.fasta')
passed('Invalid IDs show a clear error; case FASTA downloads remain available')
page.goto(BASE,wait_until='domcontentloaded');page.locator('.hero').wait_for();page.locator('.hero .molecule[data-render-state="ready"]').wait_for(timeout=30000)
page.evaluate('document.fonts.ready');page.screenshot(path=str(OUT/'final-home.png'))
assert not page.locator('a[href*="/paper/"], img[src*="/paper/"], #paper').count()
assert not any('/paper/' in url for url in requests)
passed('Homepage contains no manuscript gallery, image requests or original-figure links')
page.locator('#atlas').scroll_into_view_if_needed();expect(page.locator('#atlas .atlas-marker')).to_have_count(8)
page.wait_for_timeout(650);page.locator('#atlas').screenshot(path=str(OUT/'final-home-atlas.png'))
expect(page.locator('#atlas .atlas-map-toolbar')).to_contain_text('4,000')
for i,c in enumerate(CASES):
page.locator('#atlas .atlas-case').nth(i).click();expect(page.locator('.atlas-preview-story')).to_contain_text(c['uniref_id'][9:]);expect(page.locator('#atlas .atlas-marker')).to_have_count(8)
passed('Homepage uses the 4,000-point asset and all eight preview stories respond')
assert not page.evaluate('document.documentElement.scrollWidth>innerWidth')
for width in [390,768]:
page.set_viewport_size({'width':width,'height':844})
page.goto(BASE,wait_until='domcontentloaded');page.locator('.hero').wait_for();page.wait_for_timeout(500)
page.screenshot(path=str(OUT/f'final-home-{width}.png'))
page.locator('#atlas').scroll_into_view_if_needed();expect(page.locator('#atlas .atlas-marker')).to_have_count(8)
page.wait_for_timeout(600);page.locator('#atlas').screenshot(path=str(OUT/f'final-preview-{width}.png'))
assert not page.evaluate('document.documentElement.scrollWidth>innerWidth')
page.goto(BASE+'/atlas',wait_until='domcontentloaded');expect(page.locator('.atlas-marker')).to_have_count(8)
page.wait_for_timeout(500);page.screenshot(path=str(OUT/f'final-atlas-{width}.png'),full_page=True)
page.locator('.atlas-case').nth(7).click();expect(page.locator('.atlas-detail-body h2')).to_have_text(CASES[7]['uniref_id'])
assert not page.evaluate('document.documentElement.scrollWidth>innerWidth')
passed('390 px phone and 768 px tablet have no horizontal overflow; case selection works')
page.emulate_media(reduced_motion='reduce');page.reload(wait_until='domcontentloaded')
page.locator('.atlas-marker.selected').wait_for();assert page.locator('.atlas-map-error').count()==0
passed('Reduced-motion mode preserves map and case interactions')
assert not errors,errors
(OUT/'browser-validation.json').write_text(json.dumps({'status':'passed','checks':checks,'page_errors':errors},indent=2)+'\n')
browser.close()