Files
replypier/e2e/specs/leads/people.spec.ts
T
WangShen007 308332eb94 docs: 交付文档、维护指引与端到端回归
补齐 README、开发计划、维护交接与 E2E 用例,执行最终验收。
2026-10-21 21:40:00 +08:00

59 lines
3.2 KiB
TypeScript

import { test, expect, channels, findPerson, phoneNumber, AI_REPLY } from '@e2e'
// The People directory's edit rules, at the API the drawer uses.
test.describe('People', () => {
test('a contact can be renamed, given a phone and marked as a customer @leads', async ({ agent, llm, adminApi, request }) => {
await llm.script(agent, (s) => s.otherwise().reply('Thanks for writing in.'))
const chat = (await channels.Email({ api: adminApi, request, agentId: agent.id })).chatWith('Tess')
await chat.send('Hello')
await expect.poll(() => chat.replies(), AI_REPLY).toHaveLength(1)
const person = await findPerson(adminApi, chat.address)
const phone = phoneNumber()
await adminApi.patch(`/people/${person.id}`, { data: { full_name: 'Tess Tester', phone } })
await adminApi.post(`/people/${person.id}/mark-customer`)
expect(await adminApi.get(`/people/${person.id}`)).toMatchObject({ name: 'Tess Tester', phone, lead_stage: 'customer' })
})
test('a phone number must be international and can belong to only one person @leads', async ({ agent, llm, adminApi, request }) => {
await llm.script(agent, (s) => s.otherwise().reply('Thanks for writing in.'))
const inbox = await channels.Email({ api: adminApi, request, agentId: agent.id })
const ann = inbox.chatWith('Ann')
const ben = inbox.chatWith('Ben')
await ann.send('Hello')
await ben.send('Hello')
await expect.poll(() => ann.replies(), AI_REPLY).toHaveLength(1)
await expect.poll(() => ben.replies(), AI_REPLY).toHaveLength(1)
const annPerson = await findPerson(adminApi, ann.address)
const benPerson = await findPerson(adminApi, ben.address)
const local = await adminApi.raw('PATCH', `/people/${annPerson.id}`, { data: { phone: '07700 900123' } })
expect(local.status()).toBe(400)
expect(await local.text()).toContain('international format')
const shared = phoneNumber()
await adminApi.patch(`/people/${annPerson.id}`, { data: { phone: shared } })
const taken = await adminApi.raw('PATCH', `/people/${benPerson.id}`, { data: { phone: shared } })
expect(taken.status()).toBe(400)
expect(await taken.text()).toContain('already belongs to another person')
})
test('once a WhatsApp contact has given a real email, their number can no longer be changed away @leads', async ({ makeAgent, llm, adminApi, request }) => {
// Their phone is now the only thing an incoming WhatsApp message can find them by.
const agent = await makeAgent({ leadCapture: true })
const email = `wes.${Date.now()}@example.com`
await llm.script(agent, (s) => s.otherwise().captureLead('Thanks, noted.', { email, name: 'Wes' }))
const chat = (await channels.WhatsApp({ api: adminApi, request, agentId: agent.id })).chatWith('Wes')
await chat.send(`It is ${email}`)
await expect.poll(() => chat.replies(), AI_REPLY).toHaveLength(1)
const person = await findPerson(adminApi, email)
const response = await adminApi.raw('PATCH', `/people/${person.id}`, { data: { phone: phoneNumber() } })
expect(response.status()).toBe(400)
expect(await response.text()).toContain('how their WhatsApp messages find them')
expect((await adminApi.get<{ phone: string }>(`/people/${person.id}`)).phone).toContain(chat.waId)
})
})