85 lines
4.0 KiB
Python
85 lines
4.0 KiB
Python
import json
|
|
import subprocess
|
|
from pathlib import Path
|
|
|
|
|
|
HANDOFF = Path(__file__).parents[1] / "frontend" / "today-handoff.js"
|
|
|
|
|
|
def run_node(script: str):
|
|
result = subprocess.run(["node", "-e", script], capture_output=True, text=True)
|
|
assert result.returncode == 0, result.stderr
|
|
return json.loads(result.stdout)
|
|
|
|
|
|
def test_due_wrap_up_commitments_are_reviewed_in_order_and_added_durably():
|
|
script = f"""
|
|
const createHandoff=require({json.dumps(str(HANDOFF))});
|
|
const values=new Map();
|
|
const storage={{getItem:k=>values.get(k)||null,setItem:(k,v)=>values.set(k,v),removeItem:k=>values.delete(k)}};
|
|
const items=[
|
|
{{kind:'issue',repository:'r',number:2,title:'Second'}},
|
|
{{kind:'issue',repository:'r',number:1,title:'First'}},
|
|
];
|
|
const identity=item=>'issue:'+item.repository+':'+item.number+':';
|
|
const today=[]; const operations=[];
|
|
const controller=createHandoff({{
|
|
storage,getLogin:()=> 'timmy',identity,
|
|
todayWork:{{contains:item=>today.includes(identity(item)),add:item=>{{if(today.length>=1)return 'full';today.push(identity(item));return 'added';}}}},
|
|
todaySync:{{enqueue:(action,id)=>{{operations.push([action,id]);return true;}},flush:async()=>true}},
|
|
}});
|
|
controller.capture(['issue:r:1:','issue:r:2:','issue:r:1:']);
|
|
const review=controller.review(items);
|
|
controller.choose('issue:r:2:',false);
|
|
const first=await controller.commit(items);
|
|
controller.choose('issue:r:2:',true);
|
|
const blocked=await controller.commit(items);
|
|
process.stdout.write(JSON.stringify({{review,first,blocked,today,operations,pending:controller.pending()}}));
|
|
"""
|
|
result = run_node(f"(async()=>{{{script}}})().catch(error=>{{console.error(error);process.exit(1);}})")
|
|
assert [row["identity"] for row in result["review"]] == ["issue:r:1:", "issue:r:2:"]
|
|
assert all(row["selected"] for row in result["review"])
|
|
assert result["first"] == {"scheduled": 1, "blocked": 0, "remaining": 1}
|
|
assert result["blocked"] == {"scheduled": 0, "blocked": 1, "remaining": 1}
|
|
assert result["today"] == ["issue:r:1:"]
|
|
assert result["operations"] == [["add", "issue:r:1:"]]
|
|
assert result["pending"] == ["issue:r:2:"]
|
|
|
|
|
|
def test_handoff_pending_state_is_account_scoped_and_capture_is_idempotent():
|
|
script = f"""
|
|
const createHandoff=require({json.dumps(str(HANDOFF))});
|
|
const values=new Map();let login='timmy';
|
|
const storage={{getItem:k=>values.get(k)||null,setItem:(k,v)=>values.set(k,v),removeItem:k=>values.delete(k)}};
|
|
const options={{storage,getLogin:()=>login,identity:item=>item.id,todayWork:{{contains:()=>false,add:()=> 'added'}},todaySync:{{enqueue:()=>true,flush:async()=>true}}}};
|
|
const controller=createHandoff(options);
|
|
controller.capture(['one','two']);controller.capture(['two','one']);
|
|
const timmy=controller.pending();login='alexander';const isolated=controller.pending();
|
|
login='timmy';const resumed=createHandoff(options).pending();
|
|
process.stdout.write(JSON.stringify({{timmy,isolated,resumed}}));
|
|
"""
|
|
assert run_node(f"(async()=>{{{script}}})()") == {
|
|
"timmy": ["one", "two"], "isolated": [], "resumed": ["one", "two"],
|
|
}
|
|
|
|
|
|
def test_dashboard_packages_accessible_mobile_commitment_review_and_account_sync():
|
|
from src import main
|
|
|
|
html = main.FRONTEND_BUILD.dashboard_html
|
|
dashboard = (HANDOFF.parents[0] / "dashboard.js").read_text()
|
|
css = (HANDOFF.parents[0] / "dashboard.css").read_text()
|
|
service_worker = (HANDOFF.parents[0] / "service-worker.js").read_text()
|
|
|
|
assert 'id="today-handoff-dialog"' in html
|
|
assert 'aria-labelledby="today-handoff-title"' in html
|
|
assert 'id="today-handoff-items"' in html
|
|
assert 'id="confirm-today-handoff"' in html
|
|
assert '<script src="static/today-handoff.js"></script>' in (HANDOFF.parents[0] / "index.html").read_text()
|
|
assert "createTodayHandoff({" in dashboard
|
|
assert "laterSync.enqueue(action, itemId, wakeAt, handoff)" in dashboard
|
|
assert "todayHandoff.capture(handoffs)" in dashboard
|
|
assert ".today-handoff-actions button { min-height:44px;" in css
|
|
assert "BASE + 'static/today-handoff.js'" in service_worker
|
|
assert "static/today-handoff.js" in main.FRONTEND_BUILD.page_sources
|