mirror of
https://wget.la/https://github.com/Wxw-Gu/WechatExplorer
synced 2026-10-03 18:33:14 +08:00
feat: 重写agent hub连接器,新增对话记录和微信输入状态
- 新增 Agent Hub 对话记录面板,按会话回看机器人与微信用户的完整收发内容 - 新增微信原生正在输入状态,长任务维持 typing,异常路径强制收尾
This commit is contained in:
@@ -3,6 +3,12 @@ import userEvent from '@testing-library/user-event'
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import { AgentHubWorkspace } from '../../src/renderer/src/features/agent-hub/AgentHubWorkspace'
|
||||
import type { AgentHubStatus } from '../../src/shared/agent-hub'
|
||||
import type {
|
||||
AgentHubConversation,
|
||||
AgentHubConversationSummary
|
||||
} from '../../src/shared/agent-hub-conversation'
|
||||
|
||||
const SELF_USER_ID = 'fixture-self-openid@im.wechat'
|
||||
|
||||
const onlineStatus: AgentHubStatus = {
|
||||
hub: 'online',
|
||||
@@ -10,7 +16,43 @@ const onlineStatus: AgentHubStatus = {
|
||||
updatedAt: 1,
|
||||
dataApi: 'online',
|
||||
databaseReady: true,
|
||||
accountId: 'fixture-agent'
|
||||
accountId: 'fixture-bot-account',
|
||||
wechatUserId: SELF_USER_ID
|
||||
}
|
||||
|
||||
const conversationSummary: AgentHubConversationSummary = {
|
||||
userId: SELF_USER_ID,
|
||||
accountId: 'fixture-bot-account',
|
||||
firstAt: 1_700_000_000_000,
|
||||
lastAt: 1_700_000_060_000,
|
||||
messageCount: 2,
|
||||
lastPreview: '这是机器人的回答',
|
||||
lastDirection: 'out'
|
||||
}
|
||||
|
||||
const conversation: AgentHubConversation = {
|
||||
userId: SELF_USER_ID,
|
||||
accountId: 'fixture-bot-account',
|
||||
firstAt: 1_700_000_000_000,
|
||||
lastAt: 1_700_000_060_000,
|
||||
messages: [
|
||||
{
|
||||
id: 'm1',
|
||||
direction: 'in',
|
||||
kind: 'text',
|
||||
text: '微信里最近发生了什么',
|
||||
createdAt: 1_700_000_000_000,
|
||||
messageId: '7506247944749661000'
|
||||
},
|
||||
{
|
||||
id: 'm2',
|
||||
direction: 'out',
|
||||
kind: 'text',
|
||||
text: '这是机器人的回答',
|
||||
createdAt: 1_700_000_060_000,
|
||||
status: 'sent'
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
describe('Agent Hub controls', () => {
|
||||
@@ -35,8 +77,13 @@ describe('Agent Hub controls', () => {
|
||||
cancelAgentHubLogin: vi.fn().mockResolvedValue({ status: onlineStatus }),
|
||||
disconnectAgentHub: vi.fn().mockResolvedValue({
|
||||
status: { ...onlineStatus, connector: 'disconnected' }
|
||||
})
|
||||
} as typeof window.api
|
||||
}),
|
||||
getAgentHubConversations: vi.fn().mockResolvedValue([]),
|
||||
getAgentHubConversation: vi.fn().mockResolvedValue(null),
|
||||
clearAgentHubConversations: vi.fn().mockResolvedValue({ success: true }),
|
||||
onAgentHubConversation: vi.fn(() => () => undefined),
|
||||
onAgentHubConversationsCleared: vi.fn(() => () => undefined)
|
||||
} as unknown as typeof window.api
|
||||
})
|
||||
|
||||
it('filters, copies, and clears logs through shared controls', async () => {
|
||||
@@ -45,7 +92,7 @@ describe('Agent Hub controls', () => {
|
||||
await screen.findByText('系统就绪')
|
||||
|
||||
await user.click(screen.getByRole('combobox', { name: '筛选日志来源' }))
|
||||
await user.click(screen.getByRole('option', { name: '系统', exact: true }))
|
||||
await user.click(screen.getByRole('option', { name: '系统' }))
|
||||
expect(screen.getByText('系统就绪')).toBeInTheDocument()
|
||||
expect(screen.queryByText('等待连接')).not.toBeInTheDocument()
|
||||
|
||||
@@ -92,4 +139,56 @@ describe('Agent Hub controls', () => {
|
||||
})
|
||||
expect(window.api.disconnectAgentHub).toHaveBeenCalledOnce()
|
||||
})
|
||||
|
||||
it('把收发记录渲染成仿微信对话,左侧用软件内账号的身份', async () => {
|
||||
window.api.getAgentHubConversations = vi.fn().mockResolvedValue([conversationSummary])
|
||||
window.api.getAgentHubConversation = vi.fn().mockResolvedValue(conversation)
|
||||
|
||||
render(<AgentHubWorkspace selfInfo={{ wxid: 'wxid_me', nickname: '测试用户' }} />)
|
||||
|
||||
expect(await screen.findByText('对话记录')).toBeInTheDocument()
|
||||
// 会话标识与扫码登录账号一致时,左侧展示软件内账号的昵称。
|
||||
expect(await screen.findByText('测试用户')).toBeInTheDocument()
|
||||
expect(screen.getByText('1 个会话 · 2 条')).toBeInTheDocument()
|
||||
// 消息线程是第二次拉取,必须 await,否则在并行跑测试时会抢跑。
|
||||
expect(await screen.findByText('微信里最近发生了什么')).toBeInTheDocument()
|
||||
expect(screen.getByText('这是机器人的回答')).toBeInTheDocument()
|
||||
expect(screen.getByText('已发送')).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('对方不是本机账号时退化为占位身份,并渲染机器人头像', async () => {
|
||||
window.api.getAgentHubConversations = vi
|
||||
.fn()
|
||||
.mockResolvedValue([{ ...conversationSummary, userId: 'other-user-openid@im.wechat' }])
|
||||
window.api.getAgentHubConversation = vi.fn().mockResolvedValue({
|
||||
...conversation,
|
||||
userId: 'other-user-openid@im.wechat'
|
||||
})
|
||||
|
||||
render(<AgentHubWorkspace selfInfo={{ wxid: 'wxid_me', nickname: '测试用户' }} />)
|
||||
|
||||
expect(await screen.findByText(/微信用户 othe…enid/)).toBeInTheDocument()
|
||||
await screen.findByText('微信里最近发生了什么')
|
||||
// 右侧气泡是机器人:用固定矢量头像,不依赖真实头像资源。
|
||||
expect(document.querySelectorAll('.agent-hub-bot-avatar').length).toBeGreaterThan(0)
|
||||
})
|
||||
|
||||
it('清空对话记录需要二次确认,且不影响运行日志', async () => {
|
||||
const user = userEvent.setup()
|
||||
window.api.getAgentHubConversations = vi.fn().mockResolvedValue([conversationSummary])
|
||||
window.api.getAgentHubConversation = vi.fn().mockResolvedValue(conversation)
|
||||
|
||||
render(<AgentHubWorkspace selfInfo={null} />)
|
||||
await screen.findByText('对话记录')
|
||||
|
||||
await user.click(screen.getByRole('button', { name: '清空记录' }))
|
||||
expect(window.api.clearAgentHubConversations).not.toHaveBeenCalled()
|
||||
|
||||
await user.click(await screen.findByRole('button', { name: '确认清空' }))
|
||||
await act(async () => {
|
||||
await Promise.resolve()
|
||||
})
|
||||
expect(window.api.clearAgentHubConversations).toHaveBeenCalledOnce()
|
||||
expect(screen.getByText(/还没有收发记录/)).toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user