File size: 4,412 Bytes
d688ac7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
c5eee7b
d688ac7
 
 
 
c5eee7b
d688ac7
 
c5eee7b
d688ac7
c5eee7b
 
d688ac7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
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});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")')
 assert page.evaluate('theme')=='dark'
 # Empty root has neither text nor a hit target.
 root=page.evaluate('''()=>{let texts=[];const original=ctx.fillText;ctx.fillText=function(t,x,y){if(Math.hypot(x-W/2,y-H/2)<30)texts.push(t);return original.apply(this,arguments)};draw();ctx.fillText=original;return {texts,hit:nearest(W/2,H/2)}}''')
 assert root=={'texts':[],'hit':None},root
 page.locator('#detail').click();page.locator('#sel-close').click()
 box=page.locator('#stage').bounding_box();cx=box['x']+box['width']/2;cy=box['y']+box['height']/2
 page.mouse.move(cx,cy);page.wait_for_function('selected && selected.accession==="GCA_000001405.29"')
 assert page.locator('#selection').is_visible()
 assert page.evaluate('pinnedAssembly===null')
 assert page.locator('#sel-state').text_content().startswith('Hover preview')
 page.screenshot(path=str(R/'hover-detail.png'))
 # Hover preview clears on leaving the chart; clicking then pins the same record.
 page.mouse.move(100,100);assert page.locator('#selection').is_hidden()
 page.mouse.move(cx,cy);page.wait_for_function('selected!==null');page.mouse.click(cx,cy)
 assert page.locator('#sel-state').text_content().startswith('Frozen')
 page.mouse.move(100,100);assert page.locator('#selection').is_visible()
 assert page.locator('#sel-id').inner_text()=='GCA_000001405.29'
 # Hover another endpoint while keeping the frozen selection unchanged.
 q=page.evaluate('''()=>{const a=leaves[leaves.findIndex(a=>a.accession==='GCA_000001405.29')+12],q=screen(a.tip),r=stage.getBoundingClientRect();return {x:r.x+q[0],y:r.y+q[1],id:a.accession}}''')
 page.mouse.move(q['x'],q['y']);page.wait_for_timeout(100)
 assert page.locator('#sel-id').inner_text()=='GCA_000001405.29'
 page.mouse.move(100,100);assert page.locator('#sel-id').inner_text()=='GCA_000001405.29'
 # Both renderers and UI change theme, and the preference survives a reload.
 page.locator('#reset').click();page.locator('#theme-toggle').click();page.wait_for_function('theme==="light"')
 page.wait_for_timeout(150)
 assert page.locator('body').evaluate('e=>getComputedStyle(e).backgroundColor')=='rgb(255, 255, 255)'
 pixel=page.evaluate('''()=>{const p=new Uint8Array(4);gl.readPixels(0,0,1,1,gl.RGBA,gl.UNSIGNED_BYTE,p);return [...p]}''')
 assert pixel==[255,255,255,255],pixel
 page.screenshot(path=str(R/'light-overview.png'))
 page.reload();page.wait_for_function('window.POC && !document.querySelector("#loading")');assert page.evaluate('theme')=='light'
 page.locator('#theme-toggle').click();page.wait_for_timeout(150)
 pixel=page.evaluate('''()=>{const p=new Uint8Array(4);gl.readPixels(0,0,1,1,gl.RGBA,gl.UNSIGNED_BYTE,p);return [...p]}''')
 assert pixel==[8,14,19,255],pixel
 # Fine bar continuity: sum local alpha across successive slices through a
 # subpixel-wide diagonal bar. This catches the broken slivers from Canvas arcs.
 continuity=page.evaluate('''()=>{
  zoom=4;const a=-2.38,r0=754,r1=928,s=baseScale*zoom,m=polar((r0+r1)/2,a);pan={x:-m[0]*s,y:-m[1]*s};
  ctx.setTransform(1,0,0,1,0,0);ctx.clearRect(0,0,overlay.width,overlay.height);wedge(a-.00013,a+.00013,r0,r1,'#ffffff');
  const data=ctx.getImageData(0,0,overlay.width,overlay.height).data;let empty=0,min=Infinity,n=0;
  for(let r=r0+4/s;r<r1-4/s;r+=3/s){let [x,y]=screen(polar(r,a)),sum=0;for(let ix=Math.floor(x)-2;ix<=Math.floor(x)+2;ix++)for(let iy=Math.floor(y)-2;iy<=Math.floor(y)+2;iy++)sum+=data[(iy*overlay.width+ix)*4+3];if(sum===0)empty++;min=Math.min(min,sum);n++}
  reset();return {empty,min,samples:n};
 }''')
 assert continuity['empty']==0,continuity
 assert continuity['samples']>50
 print('hover, pin, empty root, theme persistence and bar continuity passed',continuity,flush=True)
 assert not errors,errors
 b.close()