diff --git a/frontend/human-gates.js b/frontend/human-gates.js index 1ea29f7..ad4a30e 100644 --- a/frontend/human-gates.js +++ b/frontend/human-gates.js @@ -59,6 +59,7 @@ function createHumanGates(options = {}) { const history = (item.history || []).map(event => '
  • ' + escape(event.action) + ' · ' + escape(event.at) + '
  • ').join(''); setHtml(nodes.detail, '

    ' + escape(item.title) + '

    ' + + '

    Project ' + escape(item.project) + '

    ' + '

    Exact candidate ' + escape(item.candidate_hash) + '

    ' + '

    Score ' + escape(item.score?.value ?? 'not supplied') + ' · ' + escape(item.score?.provenance || '') + '

    ' + '

    Artifacts

    Links

    ' + diff --git a/tests/test_human_gates_frontend.py b/tests/test_human_gates_frontend.py index 76eb525..358ea41 100644 --- a/tests/test_human_gates_frontend.py +++ b/tests/test_human_gates_frontend.py @@ -47,11 +47,12 @@ const gates=createHumanGates({storage:{getItem:()=>null,setItem(){}},getLogin:() def test_review_loads_exact_detail_with_links_provenance_and_history(): output = run_node(r""" -const detail={id:'g1',title:'Candidate',candidate_hash:'abc123',revision:1,checks:[{name:'unit',state:'success',required:true}],artifacts:[{name:'manifest',url:'https://forge.example/manifest'}],links:[{label:'pull',url:'https://forge.example/pull/1'}],score:{value:98,provenance:'eval/v1'},provenance:{producer:'bot',run_id:'9'},history:[{action:'intake',at:100}]}; +const detail={id:'g1',title:'Candidate',project:'stackchain/dashboard',candidate_hash:'abc123',revision:1,checks:[{name:'unit',state:'success',required:true}],artifacts:[{name:'manifest',url:'https://forge.example/manifest'}],links:[{label:'pull',url:'https://forge.example/pull/1'}],score:{value:98,provenance:'eval/v1'},provenance:{producer:'bot',run_id:'9'},history:[{action:'intake',at:100}]}; const nodes={count:{},list:{},status:{},panel:{},detail:{innerHTML:''}}; const gates=createHumanGates({storage:{getItem:()=>null,setItem(){}},getLogin:()=> 'timmy',isOnline:()=>true,nodes,location:{hash:''},fetchJson:async path=>path.endsWith('/g1')?detail:{pending_count:1,items:[detail]}}); (async()=>{await gates.load();gates.reviewNext();await new Promise(resolve=>setTimeout(resolve,0));process.stdout.write(JSON.stringify({html:nodes.detail.innerHTML}));})(); """) + assert "stackchain/dashboard" in output["html"] assert "https://forge.example/pull/1" in output["html"] assert "bot" in output["html"] assert "intake" in output["html"]