stackchain-dashboard/tests/test_issue_filing_receipt.py
timmy 4b88e1a533
All checks were successful
CI / lint (pull_request) Successful in 1m47s
CI / build-release (pull_request) Successful in 5s
CI / browser-journey (pull_request) Successful in 59s
CI / release-candidate (pull_request) Has been skipped
feat: file related issues from confirmed receipts (Closes #868)
2026-08-15 04:12:27 +00:00

114 lines
6.1 KiB
Python

import json
import subprocess
from pathlib import Path
RECEIPT = Path(__file__).parents[1] / "frontend" / "issue-filing-receipt.js"
INDEX = Path(__file__).parents[1] / "frontend" / "index.html"
CSS = Path(__file__).parents[1] / "frontend" / "dashboard.css"
DASHBOARD = Path(__file__).parents[1] / "frontend" / "dashboard.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_confirmed_delegated_issue_opens_an_accessible_shareable_receipt():
script = f"""
const createReceipt = require({json.dumps(str(RECEIPT))});
const element = () => ({{hidden:true,textContent:'',href:'',focused:false,focus(){{this.focused=true;}},addEventListener(name, fn){{this[name]=fn;}}}});
const elements = {{root:element(),heading:element(),key:element(),title:element(),ownership:element(),openLink:element(),shareButton:element(),fileAnotherButton:element(),doneButton:element(),status:element()}};
const controller = createReceipt({{...elements,navigator:{{share:async payload=>{{elements.shared=payload;}}}}}});
controller.show({{repository:'stackchain/dashboard',number:866,title:'Finish the filing journey',assignees:['alex'],url:'https://forge.example/git/stackchain/dashboard/issues/866'}}, elements.doneButton);
(async()=>{{await elements.shareButton.click();process.stdout.write(JSON.stringify({{
hidden:elements.root.hidden,key:elements.key.textContent,title:elements.title.textContent,
ownership:elements.ownership.textContent,href:elements.openLink.href,focused:elements.heading.focused,
shared:elements.shared,
}}));}})();
"""
output = run_node(script)
assert output == {
"hidden": False,
"key": "stackchain/dashboard#866",
"title": "Finish the filing journey",
"ownership": "Assigned to @alex.",
"href": "https://forge.example/git/stackchain/dashboard/issues/866",
"focused": True,
"shared": {
"title": "stackchain/dashboard#866 · Finish the filing journey",
"text": "Finish the filing journey",
"url": "https://forge.example/git/stackchain/dashboard/issues/866",
},
}
def test_unassigned_receipt_copies_link_and_escape_restores_launch_focus():
script = f"""
const createReceipt = require({json.dumps(str(RECEIPT))});
const element = () => ({{hidden:true,textContent:'',href:'',focusCount:0,focus(){{this.focusCount++;}},addEventListener(name, fn){{this[name]=fn;}}}});
const elements = {{root:element(),heading:element(),key:element(),title:element(),ownership:element(),openLink:element(),shareButton:element(),fileAnotherButton:element(),doneButton:element(),status:element()}};
const copied=[];const launcher=element();
const controller=createReceipt({{...elements,navigator:{{}},clipboard:{{writeText:async value=>copied.push(value)}}}});
controller.show({{repository:'stackchain/dashboard',number:867,title:'Unowned follow-up',assignees:[],url:'https://forge.example/git/stackchain/dashboard/issues/867'}},launcher);
(async()=>{{await elements.shareButton.click();elements.root.keydown({{key:'Escape',preventDefault(){{elements.prevented=true;}}}});process.stdout.write(JSON.stringify({{
ownership:elements.ownership.textContent,copied,status:elements.status.textContent,hidden:elements.root.hidden,
restored:launcher.focusCount,prevented:elements.prevented,
}}));}})();
"""
output = run_node(script)
assert output == {
"ownership": "Created with no owner.",
"copied": ["https://forge.example/git/stackchain/dashboard/issues/867"],
"status": "Issue link copied.",
"hidden": True,
"restored": 1,
"prevented": True,
}
def test_related_action_returns_only_the_confirmed_reusable_plan():
script = f"""
const createReceipt = require({json.dumps(str(RECEIPT))});
const element = () => ({{hidden:true,focusCount:0,focus(){{this.focusCount++;}},addEventListener(name, fn){{this[name]=fn;}}}});
const elements = {{root:element(),heading:element(),key:element(),title:element(),ownership:element(),openLink:element(),shareButton:element(),relatedButton:element(),fileAnotherButton:element(),doneButton:element(),status:element()}};
const plans=[];
const controller=createReceipt({{...elements,onFileRelated:plan=>plans.push(plan)}});
const plan={{repository:'stackchain/dashboard',title:'',body:'## Bug',labelIds:[7],templateId:'bug.yml'}};
controller.show({{repository:'stackchain/dashboard',number:868,title:'Filed',assignees:[],url:'https://forge.example/issues/868'}},elements.doneButton,plan);
elements.relatedButton.click();
process.stdout.write(JSON.stringify({{plans,hidden:elements.root.hidden,restored:elements.doneButton.focusCount}}));
"""
output = run_node(script)
assert output == {"plans": [{
"repository": "stackchain/dashboard", "title": "", "body": "## Bug",
"labelIds": [7], "templateId": "bug.yml",
}], "hidden": True, "restored": 1}
def test_mobile_shell_wires_confirmed_non_my_work_issues_to_the_receipt():
index = INDEX.read_text()
css = CSS.read_text()
dashboard = DASHBOARD.read_text()
assert 'id="issue-filing-receipt" role="dialog" aria-modal="true"' in index
assert 'id="issue-filing-receipt-heading"' in index
assert 'id="issue-filing-receipt-open"' in index
assert 'id="issue-filing-receipt-share"' in index
assert 'id="issue-filing-receipt-related"' in index
assert 'id="issue-filing-receipt-another"' in index
assert 'id="issue-filing-receipt-done"' in index
assert '<script src="static/issue-filing-receipt.js"></script>' in index
assert '.issue-filing-receipt-panel' in css
assert 'padding-bottom:calc(18px + env(safe-area-inset-bottom))' in css
assert '.issue-filing-receipt-actions' in css
assert 'min-height:44px' in css
assert 'createIssueFilingReceipt({' in dashboard
assert "relatedButton:qs('#issue-filing-receipt-related')" in dashboard
assert 'relatedDraft:issueCapture.buildRelatedDraft(durableDraft)' in dashboard
assert "issueCapture.saveDraft(plan)" in dashboard
assert "issueFilingReceipt.show(confirmed, qs('#new-issue'), filing?.relatedDraft)" in dashboard