Wait for settled material notices in browser checks
Why: A failed task card can appear before its notification turn, and the second finding must be observed while work is still running. Evidence: The strengthened browser checks first exposed missing fixture notice text and a zero-width second-stage window; after fixture correction all six task-owned HTTP/Playwright scenarios passed. Frontend 265 unit tests and build passed. Impact: Test coverage only; no production UI change. Refs: U3 r0.4 independent review Important 5
This commit is contained in:
@@ -25,7 +25,19 @@ async function setup(request:any,scenario:Scenario='normal',awaitTask=true){
|
||||
const out=await(await request.get(manifest.base+`/api/conversations/${conv.id}/cards`)).json()
|
||||
return out.cards.find((c:any)=>c.task)?.task.executionState
|
||||
}).toBe(scenario.endsWith('failure')?'failed':'completed')
|
||||
return {project,conv,ids}
|
||||
return {project,conv,ids,sendRunId:sendBody.run.id}
|
||||
}
|
||||
async function waitForFailureNotice(request:any,seed:any){
|
||||
await expect.poll(async()=>{
|
||||
const response=await request.get(manifest.base+`/api/conversations/${seed.conv.id}`)
|
||||
if(!response.ok())return false
|
||||
const current=await response.json()
|
||||
const children=current.runs.filter((r:any)=>r.kind==='subagent')
|
||||
const notices=current.messages.filter((m:any)=>m.role==='system'&&m.parts?.some((p:any)=>p.type==='text'&&p.text?.includes('后台子代理「')))
|
||||
const noticeRuns=current.runs.filter((r:any)=>r.kind==='conversation'&&r.id!==seed.sendRunId)
|
||||
return children.length>0&¬ices.length>=children.length&¬iceRuns.length>=children.length&&
|
||||
noticeRuns.every((r:any)=>['completed','failed','interrupted'].includes(r.status))
|
||||
}).toBe(true)
|
||||
}
|
||||
async function open(page:any,seed:any){
|
||||
await page.addInitScript(({id}:{id:string})=>{localStorage.setItem('as.conv',id);localStorage.setItem('as.ui',JSON.stringify({theme:'light',rightCollapsed:true,fontSize:14}))},{id:seed.conv.id})
|
||||
@@ -69,19 +81,21 @@ test('two sourced stages appear while the material task is still running',async(
|
||||
const cards=async()=>(await(await request.get(manifest.base+`/api/conversations/${seed.conv.id}/cards`)).json()).cards
|
||||
await expect.poll(async()=>{const card=(await cards()).find((c:any)=>c.task);return card?.task.executionState}).toBe('running')
|
||||
await expect(page.locator('[data-conversation-work]')).toContainText('上线六月')
|
||||
await expect.poll(async()=>{const card=(await cards()).find((c:any)=>c.task);return card?.task.findings?.length}).toBeGreaterThan(1)
|
||||
await expect.poll(async()=>{const card=(await cards()).find((c:any)=>c.task);return card?.task.executionState==='running'&&card.task.checkpointSeq>=2&&card.task.findings?.length>1}).toBe(true)
|
||||
await expect(page.locator('[data-conversation-work]')).toContainText('验收条件需要补齐')
|
||||
await expect.poll(async()=>{const card=(await cards()).find((c:any)=>c.task);return card?.task.executionState}).toBe('completed')
|
||||
})
|
||||
for(const scenario of ['zero-failure','partial-failure'] as const){
|
||||
test(`${scenario} shows the saved scope without a deliverable choice`,async({page,request})=>{
|
||||
const seed=await setup(request,scenario)
|
||||
await waitForFailureNotice(request,seed)
|
||||
await page.addInitScript(({id}:{id:string})=>{localStorage.setItem('as.conv',id);localStorage.setItem('as.ui',JSON.stringify({theme:'light',rightCollapsed:true,fontSize:14}))},{id:seed.conv.id})
|
||||
await page.goto('/')
|
||||
const work=page.locator('[data-conversation-work]')
|
||||
await expect(work).toContainText('执行失败')
|
||||
if(scenario==='zero-failure')await expect(work).toContainText('暂无阶段结论记录')
|
||||
else await expect(work).toContainText('上线六月')
|
||||
await expect(page.getByText('后台整理状态已回投工作卡;请按卡片中的结果继续。').last()).toBeVisible()
|
||||
await expect(page.locator('.hitl-choice')).toHaveCount(0)
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user