File size: 8,324 Bytes
5167728 b464afe 5167728 b464afe f7e175f b464afe f7e175f b464afe f7e175f b464afe f7e175f b464afe f7e175f b464afe 5167728 b464afe | 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 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 | import re
"""Functional smoke checks and screenshots against a running Sidereal server."""
import json
import os
from pathlib import Path
from playwright.sync_api import sync_playwright, expect
base = os.environ.get('SIDEREAL_TEST_URL', 'http://127.0.0.1:5173')
out = Path('test-results')
out.mkdir(exist_ok=True)
errors = []
with sync_playwright() as p:
installs = list(Path(os.environ.get('PLAYWRIGHT_BROWSERS_PATH', '/opt/playwright')).glob('chromium-*/chrome-linux*/chrome'))
browser = p.chromium.launch(headless=True, executable_path=str(installs[0]) if installs else None, args=['--no-sandbox'])
context = browser.new_context(viewport={'width': 1600, 'height': 1000}, device_scale_factor=1,
geolocation={'latitude': 47.3769, 'longitude': 8.5417}, permissions=['geolocation'])
page = context.new_page()
page.on('pageerror', lambda e: errors.append(str(e)))
page.goto(base, wait_until='networkidle')
expect(page.locator('canvas').first).to_be_visible()
page.get_by_role('button', name='Pause time', exact=True).click()
page.get_by_label(re.compile('Observing date and time in')).fill('2026-09-05T22:00')
def search(name):
page.get_by_label('Search sky objects').fill(name)
page.get_by_label('Search sky objects').press('Enter')
search('Vega')
expect(page.locator('.object-heading h2')).to_have_text('Vega')
expect(page.locator('.object-stats')).to_contain_text('25 ly')
page.get_by_role('button', name='CENTRE IN SKY VIEW', exact=True).click()
box = page.locator('.sky-canvas').bounding_box()
cx,cy = box['x']+box['width']/2, box['y']+box['height']/2
page.mouse.move(cx,cy)
expect(page.get_by_role('tooltip')).to_contain_text('Vega')
# An off-centre object must stay under the pointer through scroll zoom.
page.mouse.down(); page.mouse.move(cx+65,cy-42,steps=10); page.mouse.up()
page.wait_for_timeout(150)
page.mouse.move(cx+66,cy-42)
expect(page.get_by_role('tooltip')).to_contain_text('Vega')
page.mouse.wheel(0,-320)
page.wait_for_timeout(350)
page.mouse.move(cx+65,cy-42)
expect(page.get_by_role('tooltip')).to_contain_text('Vega')
page.mouse.wheel(0,320)
page.wait_for_timeout(350)
page.mouse.move(cx+66,cy-42)
expect(page.get_by_role('tooltip')).to_contain_text('Vega')
page.mouse.move(10,10)
page.screenshot(path=str(out/'desktop.png'), full_page=True)
search('M31')
expect(page.locator('.object-heading')).to_contain_text('GALAXY')
expect(page.locator('.right-rail')).to_contain_text('BEYOND OUR GALAXY')
search('Saturn')
expect(page.locator('.right-rail')).to_contain_text('THE SOLAR SYSTEM')
expect(page.get_by_role('button',name='ALL PLANETS',exact=True)).to_have_class('active')
expect(page.locator('.solar-distance')).to_contain_text('AU')
page.screenshot(path=str(out/'planet.png'), full_page=True)
search('Mars')
expect(page.get_by_role('button',name='INNER PLANETS',exact=True)).to_have_class('active')
expect(page.locator('[data-planet-position]')).to_have_count(4)
page.screenshot(path=str(out/'inner-planets.png'), full_page=True)
page.get_by_role('button',name='ALL PLANETS',exact=True).click()
expect(page.locator('[data-planet-position]')).to_have_count(8)
search('ISS')
expect(page.locator('.right-rail')).to_contain_text('EARTH / GROUND TRACK')
expect(page.locator('.object-stats')).to_contain_text('Space station')
expect(page.locator('.object-stats')).to_contain_text('1998-11-20')
page.screenshot(path=str(out/'satellite.png'), full_page=True)
for target,label in [('HST','Space telescope'),('sat733','Rocket body'),('SPACEMOBILE-001','Communications satellite')]:
search(target)
expect(page.locator('.object-stats')).to_contain_text(label)
page.screenshot(path=str(out/'communications-satellite.png'), full_page=True)
page.get_by_role('button',name='ALL SKY',exact=True).click()
expect(page.locator('.map-readout')).to_contain_text('180°')
page.get_by_role('button',name='Zoom in',exact=True).click()
expect(page.locator('.map-readout')).to_contain_text('90°')
page.get_by_role('button',name='OFF',exact=True).count() # highlights start on
page.get_by_role('button',name='ON',exact=True).click()
expect(page.get_by_role('button',name='OFF',exact=True)).to_have_attribute('aria-pressed','false')
page.get_by_role('button',name='OFF',exact=True).click()
page.get_by_label('Highlight limit').fill('100')
expect(page.locator('.range-heading')).to_contain_text('100')
page.get_by_label('Highlight limit').fill('30')
stars = page.locator('.layer-row').filter(has_text='Stars').get_by_role('checkbox')
stars.uncheck(); expect(stars).not_to_be_checked(); stars.check()
search('Vega')
page.get_by_role('button',name='CENTRE IN SKY VIEW',exact=True).click()
page.get_by_role('button',name='CONNECT SIMULATOR',exact=False).click()
expect(page.locator('.sim-label')).to_have_text('SIMULATING TRACKING')
page.get_by_label('Field of view preset').select_option('wide')
box = page.locator('.sky-canvas').bounding_box()
cx,cy = box['x']+box['width']/2,box['y']+box['height']/2
page.mouse.move(cx,cy); page.mouse.down(); page.mouse.move(cx+75,cy+20,steps=10); page.mouse.up()
expect(page.locator('.sim-label')).to_have_text('SIMULATING SLEW')
before=page.locator('.scope-strip strong').inner_text()
page.wait_for_timeout(1200)
assert page.locator('.scope-strip strong').inner_text()!=before, 'Simulated mount coordinates did not move'
page.screenshot(path=str(out/'slewing.png'),full_page=True)
page.get_by_role('button',name='STOP',exact=False).click()
expect(page.locator('.sim-label')).to_have_text('SIMULATOR STOPPED')
page.get_by_label('Field of view preset').select_option('camera')
expect(page.get_by_label('Field width in degrees')).to_have_value('0.321')
page.get_by_role('button',name='ZOOM TO FIELD',exact=False).click()
expect(page.locator('.map-readout')).to_contain_text('FIELD 1.60°')
page.screenshot(path=str(out/'field.png'),full_page=True)
page.locator('.location-top').click()
page.get_by_label('Choose a location').select_option(label='Sydney')
page.get_by_role('button',name='UPDATE SKY',exact=False).click()
expect(page.locator('.location-top')).to_contain_text('SYDNEY')
page.locator('.location-top').click()
page.get_by_label('Latitude',exact=True).focus()
page.keyboard.press('Escape')
expect(page.get_by_role('dialog')).to_have_count(0)
page.get_by_role('button',name='LOCATE ME',exact=False).click()
expect(page.locator('.location-top')).to_contain_text('CURRENT LOCATION')
expect(page.locator('.location-top')).to_contain_text('47.377')
page.get_by_role('button',name='ABOUT / DATA & CONTROLS',exact=False).click()
expect(page.get_by_role('dialog')).to_be_visible()
page.get_by_role('button',name='Close about',exact=True).click()
assert page.evaluate('document.documentElement.scrollWidth')==1600
page.set_viewport_size({'width':390,'height':844})
page.get_by_role('button',name='Reset sky view',exact=True).click()
page.screenshot(path=str(out/'mobile-sky.png'),full_page=True)
assert page.evaluate('document.documentElement.scrollWidth')==390, 'Mobile page overflows'
page.get_by_role('button',name='CONTROLS',exact=True).click()
expect(page.locator('.left-rail')).to_be_visible()
page.screenshot(path=str(out/'mobile-controls.png'),full_page=True)
page.get_by_role('button',name='OBJECT',exact=True).click()
expect(page.locator('.right-rail')).to_be_visible()
page.screenshot(path=str(out/'mobile-object.png'),full_page=True)
page.get_by_role('button',name='SKY',exact=True).click()
page.get_by_label(re.compile('Observing date and time in')).fill('2025-01-01T22:00')
page.get_by_role('button',name='CONTROLS',exact=True).click()
expect(page.locator('.left-rail')).to_contain_text('Satellite predictions unavailable')
browser.close()
print(json.dumps({'browser_errors':errors,'checks':'location, time, search, hover, all contexts, layers, zoom, draggable field, slew, stop, camera, mobile','screenshots':len(list(out.glob('*.png')))}))
assert not errors
|