77 lines
4.0 KiB
Python
77 lines
4.0 KiB
Python
import json
|
|
import subprocess
|
|
from pathlib import Path
|
|
|
|
|
|
SOURCE = Path(__file__).parents[1] / "frontend" / "release-receipt.js"
|
|
|
|
|
|
def run_node(body: str) -> dict:
|
|
script = f"const createReleaseReceipt=require({json.dumps(str(SOURCE))});\n" + body
|
|
completed = subprocess.run(["node", "-e", script], check=True, capture_output=True, text=True)
|
|
return json.loads(completed.stdout)
|
|
|
|
|
|
def test_receipt_survives_reload_for_confirmed_account_only_and_tracks_exact_commit():
|
|
output = run_node(r"""
|
|
const values=new Map();
|
|
const storage={getItem:key=>values.has(key)?values.get(key):null,setItem:(key,value)=>values.set(key,value),removeItem:key=>values.delete(key)};
|
|
let login='timmy'; const calls=[];
|
|
const first=createReleaseReceipt({storage,getLogin:()=>login,fetchJson:async path=>{calls.push(path);return {commit_sha:'merge456',ci_state:'pending',checks:[{name:'browser',state:'pending',url:''}],release:null};}});
|
|
const captured=first.capture({repository:'stackchain/api',number:7,key:'stackchain/api#7'}, {merge_commit_sha:'merge456'});
|
|
const restored=createReleaseReceipt({storage,getLogin:()=>login,fetchJson:first.fetchJson}).restore();
|
|
restored && first.refresh().then(status=>{
|
|
login='alex';
|
|
const other=createReleaseReceipt({storage,getLogin:()=>login,fetchJson:first.fetchJson}).restore();
|
|
process.stdout.write(JSON.stringify({captured,restored,status,other,calls,keys:[...values.keys()]}));
|
|
});
|
|
""")
|
|
|
|
assert output["captured"]["commit_sha"] == "merge456"
|
|
assert output["restored"]["repository"] == "stackchain/api"
|
|
assert output["status"]["label"] == "Checks running"
|
|
assert output["status"]["checks"] == ["browser"]
|
|
assert output["other"] is None
|
|
assert output["calls"] == ["api/v1/repos/stackchain/api/release-receipt/merge456"]
|
|
assert output["keys"] == ["stackchain.release-receipt.v1:timmy"]
|
|
|
|
|
|
def test_receipt_distinguishes_failed_checks_waiting_for_release_and_exact_release():
|
|
output = run_node(r"""
|
|
const values=new Map();
|
|
const storage={getItem:key=>values.get(key)||null,setItem:(key,value)=>values.set(key,value),removeItem:key=>values.delete(key)};
|
|
const responses=[
|
|
{commit_sha:'merge456',ci_state:'failure',checks:[{name:'unit',state:'success'},{name:'browser',state:'failure'}],release:null},
|
|
{commit_sha:'merge456',ci_state:'success',checks:[{name:'browser',state:'success'}],release:null},
|
|
{commit_sha:'merge456',ci_state:'success',checks:[{name:'browser',state:'success'}],release:{tag:'rc-42',url:'https://forge.example/git/x/releases/tag/rc-42',assets:[{name:'manifest.json',url:'https://forge.example/manifest'}]}},
|
|
];
|
|
const receipt=createReleaseReceipt({storage,getLogin:()=> 'timmy',fetchJson:async()=>responses.shift()});
|
|
receipt.capture({repository:'stackchain/api',number:7,key:'stackchain/api#7'}, {merge_commit_sha:'merge456'});
|
|
(async()=>{
|
|
const failed=await receipt.refresh(); const waiting=await receipt.refresh(); const released=await receipt.refresh();
|
|
receipt.dismiss();
|
|
process.stdout.write(JSON.stringify({failed,waiting,released,restored:receipt.restore()}));
|
|
})();
|
|
""")
|
|
|
|
assert output["failed"]["label"] == "Checks failed"
|
|
assert output["failed"]["checks"] == ["browser"]
|
|
assert output["waiting"]["label"] == "Checks passed · waiting for release"
|
|
assert output["released"]["label"] == "Released · rc-42"
|
|
assert output["released"]["release"]["assets"][0]["name"] == "manifest.json"
|
|
assert output["restored"] is None
|
|
|
|
|
|
def test_mobile_release_receipt_is_wired_into_the_merge_flow_and_phone_safe():
|
|
root = Path(__file__).parents[1]
|
|
html = (root / "frontend" / "index.html").read_text()
|
|
css = (root / "frontend" / "dashboard.css").read_text()
|
|
dashboard = (root / "frontend" / "dashboard.js").read_text()
|
|
|
|
assert '<script src="static/release-receipt.js"></script>' in html
|
|
assert 'id="release-receipt-launcher"' in html
|
|
assert 'id="release-receipt-sheet"' in html
|
|
assert 'releaseReceipt.capture(merging, mergeResult)' in dashboard
|
|
assert "min-height:44px" in css[css.index(".release-receipt-sheet"):]
|
|
assert "overflow-x:hidden" in css[css.index(".release-receipt-sheet"):]
|