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_view_in_filed_closes_receipt_and_routes_the_exact_confirmed_issue(): 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(),filedButton:element(),fileAnotherButton:element(),doneButton:element(),status:element()}}; const filed=[]; const controller=createReceipt({{...elements,onViewFiled:issue=>filed.push(issue)}}); controller.show({{repository:'stackchain/dashboard',number:870,title:'Delegated',assignees:['alex'],url:'https://forge.example/issues/870'}},elements.doneButton); elements.filedButton.click(); process.stdout.write(JSON.stringify({{filed,hidden:elements.root.hidden,restored:elements.doneButton.focusCount}})); """ output = run_node(script) assert output == { "filed": [{"repository": "stackchain/dashboard", "number": 870, "title": "Delegated", "assignees": ["alex"], "url": "https://forge.example/issues/870"}], "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-filed"' 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 '' 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 "filedButton:qs('#issue-filing-receipt-filed')" in dashboard assert 'onViewFiled:issue =>' in dashboard assert "confirmed.work_reasons = ['created_by_me']" 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