// Manual check: run against a fresh world on localhost:8080. Requires agent-browser and Chrome. // Set AGENT_BROWSER_EXECUTABLE_PATH if Chrome is not available at the default path. import {execFileSync} from 'node:child_process'; import assert from 'node:assert/strict'; const session='sausage-credential-ui-check'; const browser=(...args)=>execFileSync('agent-browser',['--session',session,...args],{encoding:'utf8'}).trim(); let socket; try{ console.log(browser('open','http://localhost:8080/')); socket=new WebSocket(browser('get','cdp-url')); await new Promise((resolve,reject)=>{socket.onopen=resolve;socket.onerror=reject;}); let next=0; const pending=new Map(); socket.onmessage=event=>{const message=JSON.parse(event.data);const promise=pending.get(message.id);if(promise){pending.delete(message.id);message.error?promise.reject(new Error(JSON.stringify(message.error))):promise.resolve(message.result);}}; const cdp=(method,params={},sessionId)=>new Promise((resolve,reject)=>{const id=++next;pending.set(id,{resolve,reject});socket.send(JSON.stringify({id,method,params,sessionId}));}); const {targetInfos}=await cdp('Target.getTargets'); const page=targetInfos.find(target=>target.type==='page'&&target.url==='http://localhost:8080/'); assert.ok(page,'Chat tab exists'); const {sessionId}=await cdp('Target.attachToTarget',{targetId:page.targetId,flatten:true}); await cdp('WebAuthn.enable',{},sessionId); await cdp('WebAuthn.addVirtualAuthenticator',{options:{protocol:'ctap2',transport:'internal',hasResidentKey:true,hasUserVerification:true,isUserVerified:true,automaticPresenceSimulation:true}},sessionId); browser('wait','#credential-notice:not([hidden])'); browser('click','#register-first'); browser('wait','input[name=label]'); browser('fill','input[name=label]','Browser check'); browser('click','#credential-view form button'); browser('wait','--text','Complete.'); const name='Browser check '+Date.now(); const filed=await fetch('http://localhost:8080/api/cred/requests',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({kind:'edit',key:name,request:{item:null,base_version:null,change:[{op:'create_item',config:{name,rules:[],transform_js:'',fields:[]}}]}})}); assert.equal(filed.status,200); const {request}=await filed.json(); browser('click','#credential-close'); browser('wait',`#approvals a[href="/#approve/${request}"]`); browser('click',`#approvals a[href="/#approve/${request}"]`); browser('wait','#credential-view button[value=approve]'); browser('click','#credential-view button[value=approve]'); browser('wait','--text','Complete.'); const record=await (await fetch('http://localhost:8080/api/cred/requests/'+request)).json(); assert.equal(record.state,'approved'); const items=await (await fetch('http://localhost:8080/api/cred/items')).json(); assert.ok(items.some(item=>item.name===name)); console.log('PASS: first registration, passkey approval, approved request, and created item.'); console.log(browser('screenshot','/tmp/sausage-credential-check.png')); }finally{socket?.close();browser('close');}