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