/** jsdom behavior only; no layout, browser pixels, SDK process or model calls. */
import assert from 'node:assert/strict'
import { createRequire } from 'node:module'
const externalRequire=createRequire(process.cwd()+'/package.json')
const {JSDOM}=externalRequire(process.env.YCODE_TEST_DOM_MODULE||'jsdom')
const dom=new JSDOM('
',{url:'http://localhost/',pretendToBeVisual:true})
for(const key of ['window','document','Node','Element','HTMLElement','HTMLInputElement','HTMLTextAreaElement','MouseEvent','KeyboardEvent']) Object.defineProperty(globalThis,key,{value:dom.window[key],configurable:true})
Object.defineProperty(globalThis,'navigator',{value:dom.window.navigator,configurable:true})
Object.assign(globalThis,{IS_REACT_ACT_ENVIRONMENT:true})
const React=require('react') as typeof import('react')
const {act}=React
const {createRoot}=require('react-dom/client') as typeof import('react-dom/client')
const {PermissionConfirm}=require('../src/renderer/src/workbuddy/conversation/PermissionConfirm') as typeof import('../src/renderer/src/workbuddy/conversation/PermissionConfirm')
const root=createRoot(document.getElementById('root')!)
let count=0,completed=0,declined=0, resolve!:()=>void,reject!:(e:Error)=>void
let checks=0
const check=(value:unknown,message:string)=>{assert.ok(value,message);checks++}
const options=[{optionId:'once',kind:'allow_once',name:'Once'},{optionId:'session',kind:'allow_always',name:'Session'},{optionId:'deny',kind:'reject_once',name:'Reject'}]
const pending=()=>{count++;return new Promise((yes,no)=>{resolve=yes;reject=no})}
let id='a',status:'pending'|'cancelled'='pending',defaultToNo=false
const render=()=>act(async()=>root.render({declined++}} onDecisionComplete={()=>{completed++}}/>))
const key=(value:string)=>document.querySelector('section')!.dispatchEvent(new KeyboardEvent('keydown',{key:value,bubbles:true,cancelable:true}))
const click=(selector:string)=>document.querySelector(selector)!.dispatchEvent(new MouseEvent('click',{bubbles:true,cancelable:true}))
async function main(){
await render()
check(document.activeElement?.getAttribute('data-option-id')==='once','normal prompt focuses first option')
await act(async()=>{key('1');key('1')})
check(count===1,'duplicate keyboard submission synchronous guard')
check(document.querySelectorAll('button[disabled]').length===3,'all choices disabled while submitting')
await act(async()=>reject(new Error('fixture failed')))
check(document.querySelector('[role="alert"]')?.textContent?.includes('fixture failed'),'failure visible')
await act(async()=>click('[data-option-id="once"]'))
check(count===2,'failed choice retries')
await act(async()=>resolve())
check(completed===1,'success completes once')
id='b';defaultToNo=true;await render()
check(document.activeElement?.textContent?.includes('Reject'),'default-to-no focuses reject')
await act(async()=>key('1'));check(count===2,'default-to-no has no one-key approve shortcut')
await act(async()=>key('Escape'));check(declined===1,'Escape rejects')
id='c';defaultToNo=false;await render();await act(async()=>click('[data-option-id="once"]'))
const oldResolve=resolve;const previous=completed
id='d';await render();await act(async()=>oldResolve())
check(completed===previous,'late result cannot complete replacement request')
check(document.querySelector('section')?.getAttribute('data-pending-id')==='d','replacement retained')
await act(async()=>click('[data-option-id="once"]'))
status='cancelled';await render();await act(async()=>resolve())
check(completed===previous,'cancelled request ignores stale success')
check(document.querySelector('section')?.textContent?.includes('Cancelled'),'cancelled remains visible')
id='e';status='pending';await render();await act(async()=>click('.conversation-intercept-card__rule-action'))
check(document.querySelector('[role="status"]')?.textContent?.includes('未提供命中规则详情'),'missing rule explanation explicit')
await act(async()=>root.unmount());dom.window.close()
console.log(`Permission intercept DOM: ${checks} checks passed (not pixel/SDK verification)`)
process.exit(0)
}
main().catch(error=>{console.error(error);process.exit(1)})