fix(chat): place agent activity before response
This commit is contained in:
@@ -100,7 +100,8 @@ test('does not render empty assistant bubbles between tool calls', async ({ page
|
||||
socket.__trigger('tool.completed', { ...common, event: 'tool.completed', tool_call_id: `tool-${i}`, output: 'done' })
|
||||
}
|
||||
}, sessionId)
|
||||
await expect(page.locator('.message.assistant')).toHaveCount(0)
|
||||
await expect(page.locator('.message.assistant')).toHaveCount(1)
|
||||
await expect(page.locator('.message.assistant .message-bubble')).toHaveCount(0)
|
||||
|
||||
await page.evaluate((sid) => {
|
||||
const socket = (window as any).__PW_CHAT_SOCKET__.latest
|
||||
@@ -138,7 +139,7 @@ test('groups assistant output across tool calls until the run ends', async ({ pa
|
||||
await expect(page.locator('.run-end')).toHaveText('Run output ended')
|
||||
})
|
||||
|
||||
test('animates the application logo while thinking and respects reduced motion', async ({ page }) => {
|
||||
test('shows agent activity under its own avatar before the answer', async ({ page }) => {
|
||||
await authenticate(page, TEST_ACCESS_KEY, 'research')
|
||||
await mockHermesApi(page)
|
||||
await mockChatSocket(page)
|
||||
@@ -146,15 +147,44 @@ test('animates the application logo while thinking and respects reduced motion',
|
||||
await sendChatMessage(page, 'think')
|
||||
const { sessionId } = await waitForRunSessionId(page)
|
||||
await page.evaluate((sid) => {
|
||||
(window as any).__PW_CHAT_SOCKET__.latest.__trigger('run.started', { event: 'run.started', session_id: sid, run_id: 'thinking-logo' })
|
||||
const socket = (window as any).__PW_CHAT_SOCKET__.latest
|
||||
const common = { session_id: sid, run_id: 'activity-layout' }
|
||||
socket.__trigger('run.started', { ...common, event: 'run.started' })
|
||||
socket.__trigger('tool.started', { ...common, event: 'tool.started', tool_call_id: 't1', tool: 'terminal' })
|
||||
}, sessionId)
|
||||
const avatar = page.locator('.thinking-avatar')
|
||||
await expect(avatar).toBeVisible()
|
||||
await expect(avatar).toHaveAttribute('src', '/app-logo.png')
|
||||
await expect(avatar).toHaveCSS('animation-name', /^thinking-avatar-breathe/)
|
||||
const assistant = page.locator('.message.assistant')
|
||||
await expect(assistant).toHaveCount(1)
|
||||
await expect(assistant.locator('.msg-profile-name')).toHaveText('research')
|
||||
await expect(assistant.locator('.thinking-status-label')).toBeVisible()
|
||||
await expect(assistant.locator('.live-tool-group > summary')).toHaveText('Tool calls (1)')
|
||||
await expect(assistant.locator('.message-bubble')).toHaveCount(0)
|
||||
await expect(page.locator('.thinking-avatar')).toHaveCount(0)
|
||||
await page.emulateMedia({ reducedMotion: 'reduce' })
|
||||
await expect(avatar).toHaveCSS('animation-name', 'none')
|
||||
await expect(page.locator('.thinking-status-label')).toHaveCSS('animation-name', 'none')
|
||||
await expect(assistant.locator('.thinking-status-label')).toHaveCSS('animation-name', 'none')
|
||||
await page.evaluate((sid) => {
|
||||
const socket = (window as any).__PW_CHAT_SOCKET__.latest
|
||||
const common = { session_id: sid, run_id: 'activity-layout' }
|
||||
socket.__trigger('tool.completed', { ...common, event: 'tool.completed', tool_call_id: 't1', output: 'done' })
|
||||
socket.__trigger('message.delta', { ...common, event: 'message.delta', delta: 'Final answer' })
|
||||
}, sessionId)
|
||||
await expect(assistant).toHaveCount(1)
|
||||
await expect(assistant.locator('.message-bubble')).toContainText('Final answer')
|
||||
const order = await assistant.evaluate(el => {
|
||||
const header = el.querySelector('.msg-agent-header')!
|
||||
const status = el.querySelector('.thinking-status')!
|
||||
const tool = el.querySelector('.live-tool-group')!
|
||||
const body = el.querySelector('.message-bubble')!
|
||||
return !!(header.compareDocumentPosition(status) & Node.DOCUMENT_POSITION_FOLLOWING)
|
||||
&& !!(status.compareDocumentPosition(tool) & Node.DOCUMENT_POSITION_FOLLOWING)
|
||||
&& !!(tool.compareDocumentPosition(body) & Node.DOCUMENT_POSITION_FOLLOWING)
|
||||
})
|
||||
expect(order).toBe(true)
|
||||
await page.evaluate((sid) => {
|
||||
(window as any).__PW_CHAT_SOCKET__.latest.__trigger('run.completed', { event: 'run.completed', session_id: sid, run_id: 'activity-layout' })
|
||||
}, sessionId)
|
||||
await expect(assistant.locator('.thinking-status')).toHaveCount(0)
|
||||
await expect(assistant.locator('.tool-group > summary')).toHaveText('Tool calls (1)')
|
||||
await expect(assistant.locator('.message-bubble')).toContainText('Final answer')
|
||||
})
|
||||
|
||||
test('opens the session model dialog and the session search from the chat header', async ({ page }) => {
|
||||
|
||||
@@ -22,6 +22,7 @@ test('thinking tool rows fill the chat width and shrink without overflowing', as
|
||||
})
|
||||
})
|
||||
const panel = page.locator('.tool-calls-panel')
|
||||
await panel.locator('.live-tool-group > summary').click()
|
||||
const row = panel.locator('.tool-call-item').first()
|
||||
await expect(row).toBeVisible()
|
||||
for (const width of [1920, 900, 390]) {
|
||||
|
||||
Reference in New Issue
Block a user