mirror of
https://github.com/stablyai/orca.git
synced 2026-09-22 00:02:31 +00:00
test: stabilize droid notification hook e2e (#2961)
Use the main hook status snapshot as the synthetic hook setup precondition and give the inactive-worktree notification assertions a CI-sized wait.
This commit is contained in:
@@ -21,6 +21,14 @@ type NotificationDispatch = {
|
||||
agentLastAssistantMessage?: string
|
||||
}
|
||||
|
||||
type AgentStatusSummary = {
|
||||
paneKey: string
|
||||
state: string
|
||||
agentType?: string
|
||||
prompt?: string
|
||||
lastAssistantMessage?: string
|
||||
}
|
||||
|
||||
async function emitOscTitle(page: Page, ptyId: string, title: string) {
|
||||
await sendToTerminal(page, ptyId, `printf '\\033]0;${title}\\007'\r`)
|
||||
}
|
||||
@@ -93,15 +101,7 @@ async function switchToOtherExistingWorktree(page: Page): Promise<string> {
|
||||
})
|
||||
}
|
||||
|
||||
async function getAgentStatuses(page: Page): Promise<
|
||||
{
|
||||
paneKey: string
|
||||
state: string
|
||||
agentType?: string
|
||||
prompt?: string
|
||||
lastAssistantMessage?: string
|
||||
}[]
|
||||
> {
|
||||
async function getAgentStatuses(page: Page): Promise<AgentStatusSummary[]> {
|
||||
return page.evaluate(() => {
|
||||
const store = window.__store
|
||||
if (!store) {
|
||||
@@ -117,6 +117,27 @@ async function getAgentStatuses(page: Page): Promise<
|
||||
})
|
||||
}
|
||||
|
||||
async function getCachedAgentStatuses(page: Page): Promise<AgentStatusSummary[]> {
|
||||
return page.evaluate(async () => {
|
||||
const snapshot = await window.api.agentStatus.getSnapshot()
|
||||
return snapshot.map((entry) => ({
|
||||
paneKey: entry.paneKey,
|
||||
state: entry.state,
|
||||
agentType: entry.agentType,
|
||||
prompt: entry.prompt,
|
||||
lastAssistantMessage: entry.lastAssistantMessage
|
||||
}))
|
||||
})
|
||||
}
|
||||
|
||||
async function getRendererOrCachedAgentStatuses(page: Page): Promise<AgentStatusSummary[]> {
|
||||
const [rendererStatuses, cachedStatuses] = await Promise.all([
|
||||
getAgentStatuses(page),
|
||||
getCachedAgentStatuses(page)
|
||||
])
|
||||
return [...rendererStatuses, ...cachedStatuses]
|
||||
}
|
||||
|
||||
test.describe('Droid notifications', () => {
|
||||
test('Codex hook completion dispatches while its worktree is inactive', async ({
|
||||
orcaPage,
|
||||
@@ -147,13 +168,15 @@ test.describe('Droid notifications', () => {
|
||||
await expect
|
||||
.poll(
|
||||
async () =>
|
||||
(await getAgentStatuses(orcaPage)).some(
|
||||
(await getRendererOrCachedAgentStatuses(orcaPage)).some(
|
||||
(status) =>
|
||||
status.agentType === 'codex' && status.state === 'working' && status.prompt === prompt
|
||||
),
|
||||
{
|
||||
timeout: 10_000,
|
||||
message: 'Codex UserPromptSubmit hook did not reach renderer agent status'
|
||||
timeout: 30_000,
|
||||
// Why: this synthetic hook posts directly to main; main's cache is
|
||||
// the durable source used to recover renderer startup/listener races.
|
||||
message: 'Codex UserPromptSubmit hook did not reach agent status cache'
|
||||
}
|
||||
)
|
||||
.toBe(true)
|
||||
@@ -179,7 +202,7 @@ test.describe('Droid notifications', () => {
|
||||
status.lastAssistantMessage === finalMessage
|
||||
),
|
||||
{
|
||||
timeout: 10_000,
|
||||
timeout: 30_000,
|
||||
message: 'Codex Stop hook did not reach renderer agent status'
|
||||
}
|
||||
)
|
||||
@@ -192,7 +215,7 @@ test.describe('Droid notifications', () => {
|
||||
return dispatches.filter((dispatch) => dispatch.source === 'agent-task-complete')
|
||||
},
|
||||
{
|
||||
timeout: 10_000,
|
||||
timeout: 30_000,
|
||||
message: 'Codex hook Stop did not dispatch task-complete while worktree was inactive'
|
||||
}
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user