carbon-a-release / check_dial.py
lvwerra's picture
lvwerra HF Staff
Freeze clicked strands until outside release and add verified assembly downloads
c5eee7b verified
Raw History Blame Contribute Delete
3.67 kB
from pathlib import Path
import sys,json
sys.path.insert(0,'/home/node/local/carbon-a-render/python')
from playwright.sync_api import sync_playwright
R=Path(__file__).parent
with sync_playwright() as p:
b=p.chromium.launch(executable_path='/opt/pw-browsers/chromium_headless_shell-1234/chrome-headless-shell-linux64/chrome-headless-shell',args=['--no-sandbox','--enable-webgl','--use-gl=angle','--use-angle=swiftshader','--enable-unsafe-swiftshader'])
page=b.new_page(viewport={'width':1500,'height':1050},has_touch=True);errors=[];page.on('pageerror',lambda e:errors.append(str(e)))
page.goto((R/'index.html').as_uri());page.wait_for_function('window.POC && !document.querySelector("#loading")')
def point(i,r=62):
return page.evaluate('''([i,radius])=>{const a=leaves[i],p=screen(polar(radius,a.angle)),box=stage.getBoundingClientRect();return {x:box.x+p[0],y:box.y+p[1],id:a.accession}}''',[i,r])
# Hit the same exact assembly from different radii inside all four dial sectors.
targets=[1000,11000,21500,32000]
for i in targets:
for radius in [35,78]:
q=point(i,radius);page.mouse.move(q['x'],q['y']);page.wait_for_function('(i)=>selected?.i===i',arg=i)
assert page.locator('#selection').is_visible()
assert page.locator('#sel-id').inner_text()==q['id']
assert page.locator('#tree').evaluate('e=>getComputedStyle(e).cursor')=='pointer'
assert page.evaluate('pinnedAssembly===null')
q=point(11000);page.mouse.click(q['x'],q['y']);page.mouse.move(100,100)
assert page.evaluate('pinnedAssembly.i')==11000
assert page.locator('#selection').is_visible()
# A dial drag changes angle/selection while preserving the camera, even if it
# leaves the dial. Releasing keeps the chosen assembly pinned.
page.mouse.click(100,130) # release the earlier frozen selection
a=point(1000);z=point(21500,112);camera=page.evaluate('({zoom,pan:{...pan}})')
page.mouse.move(a['x'],a['y']);page.mouse.down();page.mouse.move(z['x'],z['y'],steps=8);page.mouse.up()
assert page.evaluate('pinnedAssembly.i')==21500
assert page.evaluate('({zoom,pan})')==camera
page.screenshot(path=str(R/'dial-selection.png'))
# The mapping stays in tree coordinates under zoom and pan.
page.evaluate('''()=>{clearSelection();zoom=2.5;pan={x:-80,y:65};draw()}''')
q=point(32000);page.mouse.move(q['x'],q['y']);page.wait_for_function('selected?.i===32000')
page.mouse.click(q['x'],q['y']);assert page.evaluate('pinnedAssembly.i')==32000
# Touch taps can select through the centre as well.
page.locator('#reset').click();page.locator('#theme-toggle').click();q=point(7000)
page.touchscreen.tap(q['x'],q['y']);assert page.evaluate('pinnedAssembly.i')==7000
# The top seam resolves to a real neighbouring strand; the pivot stays stable.
seam=page.evaluate('''()=>{const right=screen(polar(60,NOON+.01)),left=screen(polar(60,NOON-.01)),centre=screen([0,0]);return [hitDial(...right)?.i,hitDial(...left)?.i,hitDial(...centre)]}''')
assert seam==[0,33587,None],seam
# Taking over with the dial stops playback and keeps the partial sweep totals.
page.locator('#animate-sweep').click();page.wait_for_function('sweep.count>100')
q=point(17000);page.mouse.click(q['x'],q['y']);assert not page.evaluate('sweep.running');assert page.evaluate('pinnedAssembly.i')==17000
before=page.evaluate('sweep.count');page.wait_for_timeout(150);assert page.evaluate('sweep.count')==before
assert page.evaluate('SWEEP_DURATION')==4000
assert not errors,errors
print(json.dumps({'dial_hover':'8 positions passed','pin':'passed','dial_drag_without_pan':'passed','zoom_and_pan':'passed','touch':'passed','top_seam':seam,'sweep_takeover':'passed','errors':errors}),flush=True)
b.close()