af49d22ca7
Add Telegram, WhatsApp and email account management, realtime messaging, contextual multilingual AI, customer intelligence, knowledge workflows, enterprise controls, a unified design system and complete repository documentation.
124 lines
5.6 KiB
TypeScript
124 lines
5.6 KiB
TypeScript
import { expect, test } from '@playwright/test'
|
|
|
|
const account = process.env.E2E_ACCOUNT || 'e2e-1785008967@local.test'
|
|
const password = process.env.E2E_PASSWORD || 'Lingxi-E2E-2026!'
|
|
|
|
test('知识库与逐句意图在真实页面可用', async ({ page }, testInfo) => {
|
|
test.skip(testInfo.project.name !== 'desktop-chromium', '仅在桌面视口执行')
|
|
|
|
const loginResponse = await page.request.post('/api/auth/login', {
|
|
data: { account, password },
|
|
})
|
|
expect(loginResponse.ok()).toBeTruthy()
|
|
const loginPayload = await loginResponse.json()
|
|
const token = loginPayload.data.token as string
|
|
const headers = { Authorization: `Bearer ${token}` }
|
|
|
|
await page.goto('/login')
|
|
await page.locator('input[autocomplete="username"]').fill(account)
|
|
await page.locator('input[autocomplete="current-password"]').fill(password)
|
|
await page.getByRole('button', { name: '登录' }).click()
|
|
await expect(page).toHaveURL(/\/dashboard/)
|
|
|
|
await page.goto('/knowledge')
|
|
await expect(page.getByText('已分段索引', { exact: true })).toBeVisible()
|
|
await expect(page.getByRole('button', { name: '上传文件' })).toBeVisible()
|
|
await page.screenshot({ path: testInfo.outputPath('knowledge-index.png'), fullPage: true })
|
|
|
|
const conversationsResponse = await page.request.get('/api/conversations', { headers })
|
|
const conversations = (await conversationsResponse.json()).data.list as Array<{ id: string }>
|
|
let conversationId = ''
|
|
let messageId = ''
|
|
let messageCount = 0
|
|
for (const conversation of conversations.slice(0, 20)) {
|
|
const messagesResponse = await page.request.get(
|
|
`/api/conversations/${encodeURIComponent(conversation.id)}/messages`,
|
|
{ headers },
|
|
)
|
|
const messages = (await messagesResponse.json()).data as Array<{
|
|
id: string
|
|
sender: string
|
|
type: string
|
|
originalText: string
|
|
intentAnalysis?: unknown
|
|
}>
|
|
const candidate = [...messages].reverse().find((message) => (
|
|
message.sender === 'customer'
|
|
&& message.type === 'text'
|
|
&& /[\p{L}]/u.test(message.originalText || '')
|
|
))
|
|
if (candidate) {
|
|
conversationId = conversation.id
|
|
messageId = candidate.id
|
|
messageCount = messages.length
|
|
break
|
|
}
|
|
}
|
|
expect(conversationId).not.toBe('')
|
|
const aiStatusResponse = await page.request.get(
|
|
`/api/conversations/${encodeURIComponent(conversationId)}/ai-status`,
|
|
{ headers },
|
|
)
|
|
expect(aiStatusResponse.ok()).toBeTruthy()
|
|
const aiStatus = (await aiStatusResponse.json()).data
|
|
expect(['not-started', 'queued', 'running', 'completed']).toContain(aiStatus.backfill.status)
|
|
if (messageCount > 80) {
|
|
await expect.poll(async () => {
|
|
const response = await page.request.get(
|
|
`/api/conversations/${encodeURIComponent(conversationId)}/ai-status`,
|
|
{ headers },
|
|
)
|
|
return (await response.json()).data.context.status
|
|
}, { timeout: 30_000 }).toBe('ready')
|
|
const readyResponse = await page.request.get(
|
|
`/api/conversations/${encodeURIComponent(conversationId)}/ai-status`,
|
|
{ headers },
|
|
)
|
|
const readyStatus = (await readyResponse.json()).data
|
|
expect(readyStatus.context.sourceMessageCount).toBeGreaterThan(0)
|
|
expect(readyStatus.context.memory.summary).toBeTruthy()
|
|
}
|
|
const analyzeResponse = await page.request.post(
|
|
`/api/conversations/${encodeURIComponent(conversationId)}/messages/${encodeURIComponent(messageId)}/analyze`,
|
|
{ headers, data: { force: true } },
|
|
)
|
|
expect(analyzeResponse.ok()).toBeTruthy()
|
|
|
|
await page.goto(`/inbox?c=${encodeURIComponent(conversationId)}`)
|
|
await expect(page.getByTestId('conversation-insight-bar')).toBeVisible()
|
|
await expect(page.getByTestId('conversation-intent-toggle')).toBeVisible()
|
|
await expect(
|
|
page.getByRole('switch', { name: '当前会话逐句意图识别' }),
|
|
).toHaveAttribute('aria-checked', 'true')
|
|
await expect.poll(() => page.getByTestId('message-intent').count()).toBeGreaterThan(0)
|
|
const intentCount = await page.getByTestId('message-intent').count()
|
|
const visibleIntent = page.getByTestId('message-intent').nth(intentCount - 1)
|
|
await visibleIntent.scrollIntoViewIfNeeded()
|
|
await expect(visibleIntent).toBeVisible()
|
|
const intentSwitch = page.getByRole('switch', { name: '当前会话逐句意图识别' })
|
|
await intentSwitch.click()
|
|
await expect(intentSwitch).toHaveAttribute('aria-checked', 'false')
|
|
await expect(page.getByTestId('message-intent')).toHaveCount(0)
|
|
await page.reload()
|
|
await expect(
|
|
page.getByRole('switch', { name: '当前会话逐句意图识别' }),
|
|
).toHaveAttribute('aria-checked', 'false')
|
|
await page.getByRole('switch', { name: '当前会话逐句意图识别' }).click()
|
|
await expect(
|
|
page.getByRole('switch', { name: '当前会话逐句意图识别' }),
|
|
).toHaveAttribute('aria-checked', 'true')
|
|
await expect.poll(() => page.getByTestId('message-intent').count()).toBeGreaterThan(0)
|
|
await expect(page.getByText('Unexpected Application Error!', { exact: true })).toHaveCount(0)
|
|
await page.screenshot({ path: testInfo.outputPath('message-intent.png'), fullPage: false })
|
|
|
|
await page.goto('/settings')
|
|
await page.getByRole('button', { name: '智能回复' }).click()
|
|
const globalIntentSwitch = page.getByRole('switch', { name: '逐条客户消息意图识别' })
|
|
await expect(globalIntentSwitch).toBeVisible()
|
|
await globalIntentSwitch.click()
|
|
await expect(globalIntentSwitch).toHaveAttribute('aria-checked', 'false')
|
|
await globalIntentSwitch.click()
|
|
await expect(globalIntentSwitch).toHaveAttribute('aria-checked', 'true')
|
|
await expect(page.getByText('invalid input syntax for type json')).toHaveCount(0)
|
|
})
|