stackchain-dashboard/tests/test_update_review_handoff.py
timmy 378291d3c8
All checks were successful
CI / lint (pull_request) Successful in 1m42s
CI / build-release (pull_request) Successful in 6s
CI / release-candidate (pull_request) Has been skipped
feat: review pull requests from update triage (Closes #775)
2026-08-13 21:59:35 +00:00

97 lines
3.7 KiB
Python

import json
import subprocess
from pathlib import Path
import pytest
from tests.dashboard_bundle import dashboard
HANDOFF = Path(__file__).resolve().parents[1] / "frontend" / "update-review-handoff.js"
def run_handoff(script):
source = f"const createHandoff = require({json.dumps(str(HANDOFF))});\n" + script
result = subprocess.run(["node", "-e", source], capture_output=True, text=True)
assert result.returncode == 0, result.stderr
return json.loads(result.stdout)
def test_review_handoff_only_admits_review_requested_pull_updates():
result = run_handoff("""
const handoff = createHandoff({openReview:()=>{}, admitRead:async()=>{}, advance:()=>{}});
const cases = [
{is_review:true, update_reason:'Review requested', subject_type:'Pull', repository:'acme/app', number:7, notification_id:41},
{is_review:true, update_reason:'Mentioned', subject_type:'Pull', repository:'acme/app', number:7, notification_id:42},
{is_review:true, update_reason:'Review requested', subject_type:'Issue', repository:'acme/app', number:7, notification_id:43},
{is_review:false, update_reason:'Review requested', subject_type:'Pull', repository:'acme/app', number:7, notification_id:44},
];
process.stdout.write(JSON.stringify(cases.map(item => handoff.eligible(item))));
""")
assert result == [True, False, False, False]
def test_review_handoff_preserves_update_on_cancel_and_advances_after_read_admission():
result = run_handoff("""
(async () => {
const events = [];
const update = {is_review:true, update_reason:'Review requested', subject_type:'Pull', repository:'acme/app', number:7, notification_id:41, title:'Ship it'};
const handoff = createHandoff({
openReview:item=>events.push(['open', item.repository, item.number]),
restoreUpdate:item=>events.push(['restore', item.notification_id]),
admitRead:async id=>events.push(['read', id]),
advance:()=>events.push(['advance']),
});
handoff.begin(update);
handoff.cancel();
handoff.begin(update);
const completed = await handoff.complete();
process.stdout.write(JSON.stringify({events, completed, active:handoff.active()}));
})().catch(error => { console.error(error); process.exit(1); });
""")
assert result == {
"events": [
["open", "acme/app", 7],
["restore", 41],
["open", "acme/app", 7],
["read", 41],
["advance"],
],
"completed": True,
"active": False,
}
def test_review_handoff_keeps_current_update_when_read_admission_fails():
result = run_handoff("""
(async () => {
const events = [];
const update = {is_review:true, update_reason:'Review requested', subject_type:'Pull', repository:'acme/app', number:7, notification_id:41};
const handoff = createHandoff({
openReview:()=>events.push('open'),
admitRead:async()=>{ events.push('read'); throw new Error('queue unavailable'); },
advance:()=>events.push('advance'),
});
handoff.begin(update);
let message = '';
try { await handoff.complete(); } catch (error) { message = error.message; }
process.stdout.write(JSON.stringify({events, message, active:handoff.active()}));
})().catch(error => { console.error(error); process.exit(1); });
""")
assert result == {"events": ["open", "read"], "message": "queue unavailable", "active": True}
@pytest.mark.anyio
async def test_dashboard_wires_review_requested_update_into_existing_review_workspace():
html = await dashboard()
assert '<script src="static/update-review-handoff.js"></script>' in html
assert 'id="review-update-now"' in html
assert "updateReviewHandoff.begin(selectedUpdate)" in html
assert "await updateReviewHandoff.complete()" in html
assert "updateReviewHandoff.cancel()" in html
assert "updateReviewHandoff.eligible(detail" in html