docs: 交付文档、维护指引与端到端回归
补齐 README、开发计划、维护交接与 E2E 用例,执行最终验收。
This commit is contained in:
1 parent
5be5ca3376
commit
308332eb94
216 files changed
+37038
No files matched your search
@@ -0,0 +1,80 @@
|
||||
import {
|
||||
test, expect, connectMessenger, connectWhatsAppNumber, digits, expectUnchanged, metaVerifiesCallback, ownMetaApp,
|
||||
pageChat, pastedCallback, routeToAgent, whereMetaSends, FakeExternals, WhatsAppChat, AI_REPLY,
|
||||
} from '@e2e'
|
||||
|
||||
// A WhatsApp number or Facebook Page connected with credentials from the
|
||||
// customer's OWN Meta app — the only way to try Meta's free test number. Meta
|
||||
// signs that app's webhooks with its own secret, so each such account has its
|
||||
// own webhook address, checked with that secret only (issue #353).
|
||||
//
|
||||
// Connected through the API: the org is shared, and once any test has a number
|
||||
// the Integrations card offers Manage, not Connect. The card itself is covered
|
||||
// by the dashboard's unit tests.
|
||||
|
||||
test.describe('a number or Page from the customer\'s own Meta app', () => {
|
||||
test('a WhatsApp number receives messages: its webhooks are pointed at ChatterMate on connect @channels', async ({ agent, llm, adminApi, request }) => {
|
||||
await llm.script(agent, (s) => s
|
||||
.when(/opening hours/i).reply('We are open 9am to 5pm, Monday to Friday.')
|
||||
.otherwise().reply('Happy to help!'))
|
||||
const app = ownMetaApp()
|
||||
const number = await connectWhatsAppNumber(adminApi, digits(15), app)
|
||||
// Meta took the per-number callback, after checking it answers: nothing to paste
|
||||
expect(number.account.webhook_auto_configured).toBe(true)
|
||||
await routeToAgent(adminApi, number.account.id, agent.id)
|
||||
|
||||
const externals = new FakeExternals(request)
|
||||
const chat = new WhatsAppChat(request, externals, number, 'Tess', () => whereMetaSends(externals, number.phoneNumberId, app))
|
||||
await chat.send('What are your opening hours?')
|
||||
|
||||
await expect.poll(() => chat.replies(), AI_REPLY).toEqual(['We are open 9am to 5pm, Monday to Friday.'])
|
||||
})
|
||||
|
||||
test('a Messenger Page receives messages once its callback URL and verify token are pasted into the app @channels', async ({ agent, llm, adminApi, request }) => {
|
||||
await llm.script(agent, (s) => s.otherwise().reply('Hi! How can we help?'))
|
||||
const app = ownMetaApp()
|
||||
const pageId = digits(15)
|
||||
const token = app.token(pageId)
|
||||
const account = await connectMessenger(adminApi, pageId, token, app.secret)
|
||||
await routeToAgent(adminApi, account.id, agent.id)
|
||||
const url = account.webhook_url ?? ''
|
||||
const verifyToken = account.webhook_verify_token ?? ''
|
||||
|
||||
// The customer pastes both into their app; Meta checks the address before saving
|
||||
expect(await metaVerifiesCallback(request, url, verifyToken)).toBe(true)
|
||||
expect(await metaVerifiesCallback(request, url, 'a-guessed-token')).toBe(false)
|
||||
|
||||
const chat = pageChat('Messenger', request, new FakeExternals(request), 'page', pageId, token, 'Remi', pastedCallback(url, app))
|
||||
await chat.send('Hello there')
|
||||
|
||||
await expect.poll(() => chat.replies(), AI_REPLY).toEqual(['Hi! How can we help?'])
|
||||
})
|
||||
|
||||
test('a wrong app secret is refused when connecting @channels', async ({ adminApi }) => {
|
||||
const app = ownMetaApp()
|
||||
await expect(connectWhatsAppNumber(adminApi, digits(15), { ...app, secret: 'not-the-app-secret' }))
|
||||
.rejects.toThrow(/400: .*That app secret is not the one for the Meta app this token comes from/)
|
||||
})
|
||||
|
||||
test('its address takes only its own app\'s accounts, never another app\'s number @channels @security', async ({ agent, llm, adminApi, request }) => {
|
||||
await llm.script(agent, (s) => s.otherwise().reply('This should never be sent.'))
|
||||
const mine = ownMetaApp()
|
||||
const ourNumber = await connectWhatsAppNumber(adminApi, digits(15), mine)
|
||||
const theirNumber = await connectWhatsAppNumber(adminApi, digits(15), ownMetaApp())
|
||||
await routeToAgent(adminApi, theirNumber.account.id, agent.id)
|
||||
const externals = new FakeExternals(request)
|
||||
|
||||
// Signed with our app's secret and sent to our address, but naming their number
|
||||
const forged = new WhatsAppChat(request, externals, theirNumber, 'Mallory', () => whereMetaSends(externals, ourNumber.phoneNumberId, mine))
|
||||
await forged.send('Hi, I am not who I say I am')
|
||||
|
||||
await expectUnchanged('replies on the other app\'s number', () => forged.replies())
|
||||
})
|
||||
|
||||
test('without the app secret a Page has no address of its own @channels', async ({ adminApi }) => {
|
||||
const pageId = digits(15)
|
||||
const account = await connectMessenger(adminApi, pageId, ownMetaApp().token(pageId))
|
||||
expect(account.webhook_url).toBeFalsy()
|
||||
expect(account.webhook_verify_token).toBeFalsy()
|
||||
})
|
||||
})
|
||||
Reference in new issue
Block a user