99 lines
2.6 KiB
TypeScript
99 lines
2.6 KiB
TypeScript
|
|
import { test as authTest, expect, type APIRequestContext } from './auth.fixture'
|
|||
|
|
import {
|
|||
|
|
buildStatusPayload,
|
|||
|
|
buildProgressPayload,
|
|||
|
|
buildCompletedPayload,
|
|||
|
|
buildDubbedPayload,
|
|||
|
|
buildFailedPayload,
|
|||
|
|
randomWorkId,
|
|||
|
|
randomEventId,
|
|||
|
|
API_BASE,
|
|||
|
|
} from '../utils/webhook-helper'
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 乐读派集成测试专用 Fixture
|
|||
|
|
* 封装 Webhook 发送、乐读派 Token API 调用等
|
|||
|
|
*/
|
|||
|
|
|
|||
|
|
type LeaiFixtures = {
|
|||
|
|
/** 发送 Webhook 请求到后端 */
|
|||
|
|
sendWebhook: (
|
|||
|
|
payload: Record<string, unknown>,
|
|||
|
|
options?: {
|
|||
|
|
eventType?: string
|
|||
|
|
validSignature?: boolean
|
|||
|
|
timestamp?: string
|
|||
|
|
},
|
|||
|
|
) => Promise<{ status: number; body: Record<string, unknown> }>
|
|||
|
|
/** 乐读派 Token API(需登录) */
|
|||
|
|
leaiTokenApi: APIRequestContext
|
|||
|
|
/** Webhook API(无需登录) */
|
|||
|
|
webhookApi: APIRequestContext
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
export const test = authTest.extend<LeaiFixtures>({
|
|||
|
|
|
|||
|
|
sendWebhook: async ({ request }, use) => {
|
|||
|
|
const sendWebhook = async (
|
|||
|
|
payload: Record<string, unknown>,
|
|||
|
|
options: {
|
|||
|
|
eventType?: string
|
|||
|
|
validSignature?: boolean
|
|||
|
|
timestamp?: string
|
|||
|
|
} = {},
|
|||
|
|
) => {
|
|||
|
|
const eventId = options.eventType === 'duplicate'
|
|||
|
|
? 'evt_duplicate_test'
|
|||
|
|
: randomEventId()
|
|||
|
|
|
|||
|
|
// 这里简化签名验证:直接构造请求
|
|||
|
|
// 实际签名需要与 LeaiApiClient.verifyWebhookSignature 对齐
|
|||
|
|
const crypto = await import('crypto')
|
|||
|
|
const body = JSON.stringify(payload)
|
|||
|
|
const timestamp = options.timestamp || Date.now().toString()
|
|||
|
|
const appSecret = 'leai_mnoi9q1a_mtcawrn8y'
|
|||
|
|
|
|||
|
|
const signData = `${eventId}.${timestamp}.${body}`
|
|||
|
|
const signature = 'HMAC-SHA256=' + crypto.createHmac('sha256', appSecret).update(signData).digest('hex')
|
|||
|
|
|
|||
|
|
const resp = await request.post(`${API_BASE}/webhook/leai`, {
|
|||
|
|
headers: {
|
|||
|
|
'X-Webhook-Id': eventId,
|
|||
|
|
'X-Webhook-Event': options.eventType || 'work.status_changed',
|
|||
|
|
'X-Webhook-Timestamp': timestamp,
|
|||
|
|
'X-Webhook-Signature': options.validSignature === false
|
|||
|
|
? 'HMAC-SHA256=invalid_signature'
|
|||
|
|
: signature,
|
|||
|
|
'Content-Type': 'application/json',
|
|||
|
|
},
|
|||
|
|
data: payload,
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
return {
|
|||
|
|
status: resp.status(),
|
|||
|
|
body: await resp.json().catch(() => ({})),
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
await use(sendWebhook)
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
leaiTokenApi: async ({ authedApi }, use) => {
|
|||
|
|
await use(authedApi)
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
webhookApi: async ({ request }, use) => {
|
|||
|
|
await use(request)
|
|||
|
|
},
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
export { expect }
|
|||
|
|
export {
|
|||
|
|
buildStatusPayload,
|
|||
|
|
buildProgressPayload,
|
|||
|
|
buildCompletedPayload,
|
|||
|
|
buildDubbedPayload,
|
|||
|
|
buildFailedPayload,
|
|||
|
|
randomWorkId,
|
|||
|
|
randomEventId,
|
|||
|
|
}
|