Publish Vulpes Preview 15 sources for desktop, Android and Tundra
Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
This commit is contained in:
parent
93e3a48004
commit
b38dea0597
25901 changed files with 9982925 additions and 369 deletions
114
tools/test-gaia-keyboard.py
Normal file
114
tools/test-gaia-keyboard.py
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
#!/usr/bin/env python3
|
||||
"""Exercise Gaia's keyboard in an isolated desktop profile. Never send a message."""
|
||||
import argparse
|
||||
import importlib.util
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
import subprocess
|
||||
import time
|
||||
|
||||
from marionette_client import Client
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
spec = importlib.util.spec_from_file_location('probe', ROOT / 'tools/probe-desktop.py')
|
||||
probe = importlib.util.module_from_spec(spec)
|
||||
spec.loader.exec_module(probe)
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument('--touch-events', action='store_true')
|
||||
parser.add_argument('--dpr', type=int, choices=(1, 3), default=1)
|
||||
parser.add_argument('--rotation', action='store_true')
|
||||
args = parser.parse_args()
|
||||
if args.dpr != 1 and not args.touch_events:
|
||||
parser.error('--dpr 3 requires --touch-events')
|
||||
|
||||
with Client(2857) as client:
|
||||
probe.register(client)
|
||||
|
||||
def evaluate(app, code):
|
||||
result = probe.evaluate(client, app, code)
|
||||
if 'value' not in result:
|
||||
raise RuntimeError(result)
|
||||
return result['value']
|
||||
|
||||
def wait(app, code):
|
||||
deadline = time.monotonic() + 12
|
||||
while time.monotonic() < deadline:
|
||||
result=probe.evaluate(client, app, code)
|
||||
if result.get('value'):
|
||||
return
|
||||
if 'error' in result:
|
||||
raise RuntimeError(result['error'])
|
||||
time.sleep(.15)
|
||||
raise TimeoutError(code)
|
||||
|
||||
def tap(app, selector):
|
||||
if app == 'keyboard':
|
||||
selector = '.keyboard-type-container[data-active] ' + selector
|
||||
rect = evaluate(app, 'return document.querySelector(' + json.dumps(selector) + ').getBoundingClientRect().toJSON();')
|
||||
point = {'x': rect['x'] + rect['width'] / 2, 'y': rect['y'] + rect['height'] / 2}
|
||||
if args.touch_events:
|
||||
script = '''const done=arguments[arguments.length-1];
|
||||
const w=Services.wm.getMostRecentWindow('vulpes:host');
|
||||
function find(b){if(b.currentWindowGlobal?.documentURI.spec.startsWith(PREFIX))return b;
|
||||
for(const c of b.children){const f=find(c);if(f)return f;}}
|
||||
find(w.document.getElementById('system').browsingContext).currentWindowGlobal
|
||||
.getActor('VulpesProbe').sendQuery('Tap',POINT).then(done,e=>done({error:String(e)}));'''
|
||||
script = script.replace('PREFIX', json.dumps('http://' + app + '.localhost:8765/')).replace('POINT', json.dumps(point))
|
||||
result = client.call('WebDriver:ExecuteAsyncScript', {
|
||||
'script': script, 'args': [], 'newSandbox': True, 'sandbox': 'system',
|
||||
})['value']
|
||||
assert result is True, result
|
||||
else:
|
||||
frame_selector = '#vulpes-gaia-keyboard' if app == 'keyboard' else 'iframe[src^="http://' + app + '.localhost:8765/"]'
|
||||
frame = evaluate('system', 'return document.querySelector(' + json.dumps(frame_selector) + ').getBoundingClientRect().toJSON();')
|
||||
subprocess.run(['xdotool', 'search', '--name', '^Vulpes', 'windowraise',
|
||||
'windowfocus', 'mousemove', '--window', '%1',
|
||||
str(round(frame['x'] + point['x'])), str(round(frame['y'] + point['y'])),
|
||||
'click', '1'], env=os.environ, check=True)
|
||||
time.sleep(.35)
|
||||
|
||||
def size(width, height):
|
||||
client.execute(f"const w=Services.wm.getMostRecentWindow('vulpes:host');w.document.documentElement.style.minWidth='0';w.document.documentElement.style.minHeight='0';w.resizeTo({width},{height});return true;")
|
||||
time.sleep(.6)
|
||||
|
||||
wait('system', 'return document.body?.getAttribute("ready-state")==="fullyLoaded";')
|
||||
client.execute(f"Services.prefs.setCharPref('layout.css.devPixelsPerPx','{args.dpr}');return true;")
|
||||
size(360, 740)
|
||||
evaluate('system', 'ScreenManager.turnScreenOn(true);if(Service.query("locked"))await Service.request("unlock",{forcibly:true});return true;')
|
||||
time.sleep(1)
|
||||
evaluate('system', 'await VulpesCompat.call("apps.launch",{manifestURL:"http://sms.localhost:8765/manifest.webapp"});return true;')
|
||||
wait('sms', 'return !!window.Navigation;')
|
||||
evaluate('sms', 'await Navigation.toPanel("thread-list");await Navigation.toPanel("composer");return true;')
|
||||
tap('sms', '.recipient[contenteditable]')
|
||||
wait('keyboard', 'return navigator.mozInputMethod?.inputcontext?.inputType==="tel" && !!document.querySelector("button[aria-label=\\"2\\"]");')
|
||||
tap('keyboard', 'button[aria-label="2"]')
|
||||
tap('keyboard', 'button[aria-label="3"]')
|
||||
number = evaluate('sms', 'return document.querySelector(".recipient[contenteditable]").textContent;')
|
||||
assert number.strip() == '23', number
|
||||
numeric_height = evaluate('keyboard', 'return document.querySelector("button[aria-label=\\"2\\"]").getBoundingClientRect().height;')
|
||||
assert numeric_height >= 44, numeric_height
|
||||
tap('sms', '#messages-input')
|
||||
wait('keyboard', 'return navigator.mozInputMethod?.inputcontext?.inputType==="text" && !!document.querySelector("button[aria-label=\\"a\\"]");')
|
||||
tap('keyboard', 'button[aria-label="a"]')
|
||||
text = evaluate('sms', 'return document.querySelector("#messages-input").textContent;')
|
||||
assert text.lower() == 'a', text
|
||||
assert evaluate('sms', 'return document.querySelector(".recipient[contenteditable]").textContent;') == number, 'Letter changed the recipient'
|
||||
evaluate('sms', 'getSelection().setPosition(document.querySelector("#messages-input").firstChild,0);return true;')
|
||||
tap('keyboard', 'button[aria-label="b"]')
|
||||
assert evaluate('sms', 'return document.querySelector("#messages-input").textContent.toLowerCase();') == 'ba'
|
||||
tap('keyboard', 'button[data-keycode="8"]')
|
||||
assert evaluate('sms', 'return document.querySelector("#messages-input").textContent.toLowerCase();') == 'a'
|
||||
report = {'passed': True, 'sent': False, 'dpr': args.dpr,
|
||||
'recipientUnchanged': True, 'messageTyped': True, 'caretAndBackspace': True,
|
||||
'numericKeyHeight': numeric_height}
|
||||
if args.rotation:
|
||||
size(740, 360)
|
||||
wait('keyboard', 'return !app.viewManager.screenInPortraitMode();')
|
||||
report['landscape'] = evaluate('keyboard', 'return {width:innerWidth,height:innerHeight,rem:app.viewManager.getRemToPx(),font:parseFloat(getComputedStyle(document.documentElement).fontSize)};')
|
||||
assert abs(report['landscape']['font'] - report['landscape']['width'] / 64) < .05
|
||||
size(360, 740)
|
||||
wait('keyboard', 'return app.viewManager.screenInPortraitMode();')
|
||||
report['portrait'] = evaluate('keyboard', 'return {height:innerHeight,key:document.querySelector("button[aria-label=\\"a\\"]").getBoundingClientRect().height,font:parseFloat(getComputedStyle(document.documentElement).fontSize)};')
|
||||
assert report['portrait']['key'] >= 44, report
|
||||
print(json.dumps(report))
|
||||
Loading…
Reference in a new issue