117 lines
3.6 KiB
Python
117 lines
3.6 KiB
Python
import json
|
|
import subprocess
|
|
from pathlib import Path
|
|
|
|
|
|
POLLER = Path(__file__).parents[1] / "frontend" / "context-poller.js"
|
|
|
|
|
|
def run_node(script: str) -> dict:
|
|
result = subprocess.run(
|
|
["node", "-e", script], check=True, capture_output=True, text=True
|
|
)
|
|
return json.loads(result.stdout)
|
|
|
|
|
|
def test_context_poller_is_single_flight_and_pauses_until_visible():
|
|
script = f"""
|
|
const createContextPoller = require({json.dumps(str(POLLER))});
|
|
let calls = 0;
|
|
let hidden = false;
|
|
let resolveRequest;
|
|
const timers = [];
|
|
const poller = createContextPoller({{
|
|
fetchContext: () => {{
|
|
calls += 1;
|
|
if (calls > 1) return Promise.resolve({{ repos: [] }});
|
|
return new Promise((resolve) => {{ resolveRequest = resolve; }});
|
|
}},
|
|
onSnapshot: () => {{}},
|
|
onError: () => {{}},
|
|
isHidden: () => hidden,
|
|
setTimer: (callback) => {{ timers.push(callback); return timers.length; }},
|
|
clearTimer: () => {{}},
|
|
intervalMs: 8000,
|
|
}});
|
|
|
|
(async () => {{
|
|
const first = poller.start();
|
|
const joined = poller.refresh();
|
|
const callsWhilePending = calls;
|
|
resolveRequest({{ repos: [] }});
|
|
await Promise.all([first, joined]);
|
|
|
|
hidden = true;
|
|
poller.setVisible(false);
|
|
const scheduled = timers.shift();
|
|
if (scheduled) scheduled();
|
|
await Promise.resolve();
|
|
const callsWhileHidden = calls;
|
|
|
|
hidden = false;
|
|
await poller.setVisible(true);
|
|
process.stdout.write(JSON.stringify({{
|
|
callsWhilePending,
|
|
callsWhileHidden,
|
|
callsAfterResume: calls,
|
|
}}));
|
|
}})();
|
|
"""
|
|
|
|
assert run_node(script) == {
|
|
"callsWhilePending": 1,
|
|
"callsWhileHidden": 1,
|
|
"callsAfterResume": 2,
|
|
}
|
|
|
|
|
|
def test_context_poller_sends_revisions_and_merges_changed_sections():
|
|
script = f"""
|
|
const createContextPoller = require({json.dumps(str(POLLER))});
|
|
const requested = [];
|
|
const rendered = [];
|
|
const responses = [
|
|
{{ context: {{ user: {{ login: 'timmy' }} }}, events: [{{ id: 1 }}], notifications: [],
|
|
sections: {{ context: 'fresh', events: 'fresh', notifications: 'fresh' }},
|
|
revisions: {{ context: 1, events: 1, notifications: 1 }}, freshness: {{ age_seconds: 0 }} }},
|
|
{{ sections: {{ context: 'fresh', events: 'fresh', notifications: 'fresh' }},
|
|
revisions: {{ context: 1, events: 2, notifications: 1 }}, events: [{{ id: 2 }}],
|
|
freshness: {{ age_seconds: 1 }} }},
|
|
{{ sections: {{ context: 'fresh', events: 'fresh', notifications: 'fresh' }},
|
|
revisions: {{ context: 1, events: 2, notifications: 1 }}, freshness: {{ age_seconds: 2 }} }},
|
|
];
|
|
const poller = createContextPoller({{
|
|
fetchContext: revisions => {{ requested.push({{ ...revisions }}); return Promise.resolve(responses.shift()); }},
|
|
onSnapshot: (snapshot, changed) => rendered.push({{
|
|
context: snapshot.context.user.login,
|
|
event: snapshot.events[0].id,
|
|
age: snapshot.freshness.age_seconds,
|
|
changed,
|
|
}}),
|
|
onError: error => {{ throw error; }},
|
|
setTimer: () => 1,
|
|
clearTimer: () => {{}},
|
|
}});
|
|
(async () => {{
|
|
await poller.refresh();
|
|
await poller.refresh();
|
|
await poller.refresh();
|
|
process.stdout.write(JSON.stringify({{ requested, rendered }}));
|
|
}})();
|
|
"""
|
|
|
|
assert run_node(script) == {
|
|
"requested": [
|
|
{},
|
|
{"context": 1, "events": 1, "notifications": 1},
|
|
{"context": 1, "events": 2, "notifications": 1},
|
|
],
|
|
"rendered": [
|
|
{"context": "timmy", "event": 1, "age": 0,
|
|
"changed": ["context", "events", "notifications"]},
|
|
{"context": "timmy", "event": 2, "age": 1,
|
|
"changed": ["events"]},
|
|
{"context": "timmy", "event": 2, "age": 2, "changed": []},
|
|
],
|
|
}
|