VulpesOS/tundra/tools/test-beatles-browser.py
2026-10-22 20:42:26 +02:00

95 lines
3.9 KiB
Python

#!/usr/bin/env python3
# SPDX-License-Identifier: MPL-2.0
"""Check browser address entry with the Nokia keypad in a manual Gaia session.
Uses a local HTTP response and a reserved .invalid hostname, without relying
on Internet access. Does not send messages, call, reboot or flash the phone.
"""
import argparse
import importlib.util
import json
from pathlib import Path
import time
spec = importlib.util.spec_from_file_location('controls', Path(__file__).with_name('test-beatles-controls.py'))
controls = importlib.util.module_from_spec(spec)
spec.loader.exec_module(controls)
probe, inject = controls.probe, controls.inject
def until(script, timeout=15):
deadline = time.monotonic()+timeout
while time.monotonic() < deadline:
result = probe(script)
if result:
return result
time.sleep(.2)
raise TimeoutError(script)
def address():
# Up scrolls a long page first; once at the top it returns to the toolbar.
for _ in range(8):
if probe('return document.activeElement.classList.contains("urlbar");'):
break
inject('ArrowUp')
time.sleep(.35)
until('return document.activeElement.classList.contains("urlbar");')
inject('Enter')
until('return document.activeElement.id === "rocketbar-input";')
def navigate(url):
probe('const e=document.querySelector("#rocketbar-input");e.value='+json.dumps(url)+';e.dispatchEvent(new Event("input",{bubbles:true}));return true;')
inject('Enter')
until('return !document.querySelector("#rocketbar").classList.contains("active") && [...document.querySelectorAll("iframe")].some(f=>f.dataset.url==='+json.dumps(url)+');')
time.sleep(3)
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('--output', type=Path, required=True)
args = parser.parse_args()
report = {'device':'beatles','internetAccessRequired':False}
try:
probe('await VulpesCompat.call("apps.launch",{manifestURL:"http://search.localhost:8765/manifest.webapp"});return true;')
until('return [...document.querySelectorAll(".urlbar")].some(e=>e.checkVisibility({checkOpacity:true,checkVisibilityCSS:true}) && e.getBoundingClientRect().width>0);')
address()
report['addressFocusFromWelcome'] = True
probe('const e=document.querySelector("#rocketbar-input");e.value="";e.dispatchEvent(new Event("input",{bubbles:true}));return true;')
inject('2')
until('return document.querySelector("#rocketbar-input").value === "a";')
report['multitapInput'] = True
inject('Escape')
until('return !document.querySelector("#rocketbar").classList.contains("active");')
report['cancelAddress'] = True
address()
# The Gaia server returns an HTTP 421 document for an unregistered host.
# This exercises the top-level web view without a network dependency.
navigate('http://127.0.0.1:8765/')
address()
report['addressFocusFromWebView'] = True
inject('Escape')
until('return !document.querySelector("#rocketbar").classList.contains("active");')
inject('ArrowUp')
until('return document.activeElement.classList.contains("urlbar");')
inject('ArrowDown')
until('return document.activeElement.localName === "iframe";')
report['toolbarToPage'] = True
address()
navigate('https://vulpes-keypad-test.invalid/')
address()
report['addressFocusFromNetworkError'] = True
# Leave the real welcome page open for the user.
navigate('http://search.localhost:8765/home/index.html')
address()
probe('const e=document.querySelector("#rocketbar-input");e.select();return true;')
report['readyForManualAddressEntry'] = True
finally:
args.output.parent.mkdir(parents=True,exist_ok=True)
args.output.write_text(json.dumps(report,indent=2)+'\n')
print(json.dumps(report,indent=2))
if __name__ == '__main__':
main()