File size: 5,838 Bytes
6ba5297
ff2a0f1
 
 
 
 
 
 
 
 
 
63f9816
ff2a0f1
 
 
63f9816
 
ff2a0f1
 
 
 
 
 
 
424d5aa
ff2a0f1
6ba5297
ff2a0f1
 
 
 
 
 
 
 
 
 
6ba5297
ff2a0f1
 
 
6ba5297
 
 
 
ff2a0f1
63f9816
6ba5297
 
 
ff2a0f1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6ba5297
ff2a0f1
 
 
 
 
 
 
 
 
 
6ba5297
ff2a0f1
 
 
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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
import asyncio,json,math,os,re
from pathlib import Path
OUTPUT=Path(os.environ.get("SIDEREAL_TEST_OUTPUT","/tmp/sidereal-deep-check"))
OUTPUT.mkdir(parents=True,exist_ok=True)
from datetime import datetime,timezone
from playwright.async_api import async_playwright

async def main():
 async with async_playwright() as p:
  browser=await p.chromium.launch(headless=True,executable_path=os.environ.get('CHROMIUM_EXECUTABLE','/opt/pw-browsers/chromium-1234/chrome-linux64/chrome'),args=['--no-sandbox'])
  page=await browser.new_page(viewport={'width':1440,'height':1000})
  errors=[];requests=[];responses=[];response_ready=asyncio.Event()
  page.on('pageerror',lambda e:errors.append(str(e)))
  page.on('request',lambda r:requests.append(r.url) if '/api/stars/deep?' in r.url else None)
  async def response(r):
   if '/api/stars/deep?' in r.url and r.status==200:
    responses.append(await r.json());response_ready.set()
  page.on('response',response)
  await page.clock.set_fixed_time(datetime(2026,9,6,20,tzinfo=timezone.utc))
  await page.add_init_script("""
   localStorage.setItem('sidereal-site',JSON.stringify({name:'Bern',lat:46.948,lon:7.4474,elevation:540}));
   window.faintDots=[];
   const clear=CanvasRenderingContext2D.prototype.clearRect,arc=CanvasRenderingContext2D.prototype.arc;
   CanvasRenderingContext2D.prototype.clearRect=function(...args){if(!this.canvas.classList.contains('map-overlay'))window.faintDots=[];return clear.apply(this,args)};
   CanvasRenderingContext2D.prototype.arc=function(x,y,r,...rest){if(r>=0.85&&r<=1.2&&!this.canvas.classList.contains('map-overlay'))window.faintDots.push({x,y});return arc.call(this,x,y,r,...rest)};
  """)
  base=os.environ.get('SIDEREAL_TEST_URL','http://127.0.0.1:7866')
  if 'hf.space' in base:
   async def auth(route):await route.continue_(headers={**route.request.headers,'Authorization':'Bearer '+os.environ['HF_TOKEN']})
   await page.route('https://lvwerra-sidereal.hf.space/**',auth)
  await page.goto(base,wait_until='networkidle')
  assert not requests
  slider=page.get_by_label('Faintest displayed star magnitude')
  assert await slider.get_attribute('max')=='14'
  await page.get_by_label('Search sky objects').fill('Vega')
  await page.locator('.search-results button').first.click()
  await slider.fill('14')
  assert '10°' in await page.locator('.deep-star-status').inner_text()
  await page.wait_for_timeout(500)
  assert not requests
  await page.get_by_role('button',name='ZOOM FOR FAINT STARS',exact=False).click()
  await page.wait_for_function("document.querySelector('.deep-star-status')?.textContent.includes('Dense field') || document.querySelector('.deep-star-status')?.textContent.includes('Gaia field loaded')",timeout=45000)
  initial=await page.locator('.sky-canvas').bounding_box()
  await page.mouse.move(initial['x']+initial['width']/2,initial['y']+initial['height']/2)
  await page.mouse.wheel(0,math.log(.2)/.0015)
  await page.wait_for_function("document.querySelector('.deep-star-status')?.textContent.includes('Gaia field loaded')",timeout=45000)
  await asyncio.wait_for(response_ready.wait(),5)
  assert len(responses)==2 and len(responses[-1]['stars'])>500,(requests,len(responses))
  assert max(s['mag'] for s in responses[-1]['stars'])>13.9
  assert not responses[-1]['truncated']
  await page.wait_for_timeout(150)
  box=await page.locator('.sky-canvas').bounding_box()
  dots=await page.evaluate('window.faintDots')
  selected=False
  for dot in dots[::max(1,len(dots)//30)]:
   if not(50<dot['x']<box['width']-50 and 50<dot['y']<box['height']-50):continue
   await page.mouse.move(box['x']+dot['x'],box['y']+dot['y'])
   await page.wait_for_timeout(30)
   tooltip=page.get_by_role('tooltip')
   if await tooltip.count() and 'Gaia DR3' in await tooltip.inner_text():
    await page.screenshot(path=str(OUTPUT/'deep-tooltip.png'))
    await page.mouse.click(box['x']+dot['x'],box['y']+dot['y'])
    selected=True;break
  assert selected,'No Gaia hover/click target'
  assert 'Gaia DR3' in await page.locator('.object-heading h2').inner_text()
  assert await page.get_by_text('APPARENT MAGNITUDE / G',exact=True).is_visible()
  selected_name=await page.locator('.object-heading h2').inner_text()
  assert 'FIELD 2.00°' in await page.locator('.map-readout').inner_text()
  await page.screenshot(path=str(OUTPUT/'deep-desktop.png'))
  before=len(requests)
  await page.get_by_role('button',name='Zoom in',exact=True).click()
  await page.wait_for_timeout(800)
  assert len(requests)==before,'Zoom-in should reuse the containing cone'
  await page.get_by_label('Search sky objects').fill(selected_name)
  await page.locator('.search-results button').first.click()
  assert await page.locator('.object-heading h2').inner_text()==selected_name
  assert 'FIELD 1.20°' in await page.locator('.map-readout').inner_text()
  await page.get_by_role('button',name='ALL SKY',exact=True).click()
  assert '10°' in await page.locator('.deep-star-status').inner_text()
  assert await page.locator('.object-heading h2').inner_text()==selected_name
  await page.screenshot(path=str(OUTPUT/'pass-galaxies.png'))
  assert await page.locator('.galaxy-symbol').count()>0
  for width in [390,320]:
   await page.set_viewport_size({'width':width,'height':844})
   await page.get_by_role('button',name='CONTROLS',exact=True).click()
   assert await slider.is_visible()
   assert not await page.evaluate('document.documentElement.scrollWidth>innerWidth')
   await page.screenshot(path=str(OUTPUT/f'deep-mobile-{width}.png'))
  assert not errors,errors
  print(f'PASSED {base}: {len(responses[-1]["stars"])} Gaia entries through {max(s["mag"] for s in responses[-1]["stars"]):.2f}; zoom gate, hover, click, G-band details, cone reuse, selection/search, full-sky mode, mobile. Browser errors: {errors}')
  await browser.close()

asyncio.run(main())