92 lines
3.1 KiB
Python
92 lines
3.1 KiB
Python
import json
|
|
import subprocess
|
|
from pathlib import Path
|
|
|
|
|
|
ROOT = Path(__file__).resolve().parents[1]
|
|
RECONNECT = ROOT / "frontend" / "reconnect-outboxes.js"
|
|
|
|
|
|
def run_node(script: str) -> dict:
|
|
result = subprocess.run(
|
|
["node", "-e", script], cwd=ROOT, text=True, capture_output=True, check=True
|
|
)
|
|
return json.loads(result.stdout)
|
|
|
|
|
|
def test_successful_reconnect_restores_identity_and_flushes_unchanged_outboxes():
|
|
result = run_node(
|
|
f"""
|
|
const createReconnectOutboxes = require({json.dumps(str(RECONNECT))});
|
|
const calls = [];
|
|
const reconnect = createReconnectOutboxes({{
|
|
refresh: async () => ({{context:{{user:{{login:'timmy'}}}}}}),
|
|
restoreIdentity: login => calls.push(['identity', login]),
|
|
flushIssue: () => calls.push(['issue']),
|
|
flushAuthored: () => calls.push(['authored']),
|
|
flushNotificationReads: () => calls.push(['notification-read']),
|
|
}});
|
|
reconnect().then(result => process.stdout.write(JSON.stringify({{result, calls}})));
|
|
"""
|
|
)
|
|
|
|
assert result == {
|
|
"result": True,
|
|
"calls": [
|
|
["identity", "timmy"],
|
|
["issue"],
|
|
["authored"],
|
|
["notification-read"],
|
|
],
|
|
}
|
|
|
|
|
|
def test_concurrent_reconnect_requests_queue_one_follow_up_flush():
|
|
result = run_node(
|
|
f"""
|
|
const createReconnectOutboxes = require({json.dumps(str(RECONNECT))});
|
|
(async () => {{
|
|
let releaseFirst; let issueCalls=0; let active=0; let maxActive=0;
|
|
const reconnect = createReconnectOutboxes({{
|
|
refresh: async () => ({{context:{{user:{{login:'timmy'}}}}}}),
|
|
restoreIdentity: () => {{}},
|
|
flushIssue: async () => {{
|
|
issueCalls++; active++; maxActive=Math.max(maxActive,active);
|
|
if (issueCalls === 1) await new Promise(resolve => {{ releaseFirst=resolve; }});
|
|
active--;
|
|
}},
|
|
flushAuthored: async () => {{}},
|
|
flushNotificationReads: async () => {{}},
|
|
}});
|
|
const first=reconnect();
|
|
while (!releaseFirst) await new Promise(resolve=>setTimeout(resolve,0));
|
|
const second=reconnect();
|
|
releaseFirst();
|
|
await Promise.all([first,second]);
|
|
process.stdout.write(JSON.stringify({{issueCalls,maxActive}}));
|
|
}})().catch(error => {{ console.error(error); process.exit(1); }});
|
|
"""
|
|
)
|
|
|
|
assert result == {"issueCalls": 2, "maxActive": 1}
|
|
|
|
|
|
def test_dashboard_uses_reconnect_flush_after_live_identity_refresh():
|
|
index = (ROOT / "frontend" / "index.html").read_text()
|
|
dashboard = (ROOT / "frontend" / "dashboard.js").read_text()
|
|
|
|
assert '<script src="static/reconnect-outboxes.js"></script>' in index
|
|
assert "const reconnectOutboxes = createReconnectOutboxes({" in dashboard
|
|
assert "restoreIdentity: login => { activeFlushLogin = login; confirmedOwnerLogin = login; }" in dashboard
|
|
assert "window.addEventListener('online', reconnectAfterOnline);" in dashboard
|
|
assert "setTimeout(reconnectOutboxes, 500)" in dashboard
|
|
|
|
|
|
def test_dashboard_registers_reconnect_before_offline_startup_can_wait():
|
|
dashboard = (ROOT / "frontend" / "dashboard.js").read_text()
|
|
|
|
listener = dashboard.index("window.addEventListener('online', reconnectAfterOnline);")
|
|
offline_startup = dashboard.index("await updateOfflineWorkControls();")
|
|
|
|
assert listener < offline_startup
|