import assert from 'node:assert/strict'; import { createNotificationAdaptersFromEnvironment, HttpNotificationAdapter, NotificationError } from '../dist/notifications/notification-service.js'; const requests = []; const fetcher = async (url, init) => { requests.push({ url: String(url), init }); return { ok: true, status: 200, headers: { get(name) { return name === 'x-request-id' ? 'provider-request-1' : null; } }, async json() { return { providerMessageId: 'provider-message-1' }; } }; }; const adapters = createNotificationAdaptersFromEnvironment({ QIPAI_NOTIFICATION_WECHAT_GATEWAY_URL: 'https://gateway.example.test/wechat', QIPAI_NOTIFICATION_WECHAT_GATEWAY_TOKEN: 'wechat-secret', QIPAI_NOTIFICATION_WECOM_GATEWAY_URL: 'https://gateway.example.test/wecom', QIPAI_NOTIFICATION_CLOUD_SPEAKER_GATEWAY_URL: 'https://gateway.example.test/speaker', QIPAI_NOTIFICATION_HTTP_TIMEOUT_MS: '5000' }, fetcher); assert.deepEqual([...adapters.keys()], [ 'IN_APP', 'WEBHOOK', 'WECHAT_SUBSCRIBE', 'WE_COM', 'CLOUD_SPEAKER' ]); const input = { deliveryId: '31', tenantId: '7', channel: 'WECHAT_SUBSCRIBE', recipientId: '21', title: '提醒', body: '订单已支付', payload: { orderId: '41' }, externalTemplateId: 'template-1' }; assert.deepEqual(await adapters.get('WECHAT_SUBSCRIBE').send(input), { providerMessageId: 'provider-message-1' }); assert.equal(requests[0].url, 'https://gateway.example.test/wechat'); assert.equal(requests[0].init.headers.authorization, 'Bearer wechat-secret'); assert.equal(requests[0].init.headers['idempotency-key'], 'notification:31'); assert.equal(JSON.parse(requests[0].init.body).externalTemplateId, 'template-1'); await adapters.get('WEBHOOK').send({ ...input, channel: 'WEBHOOK', recipientId: 'https://store.example.test/hooks/notify' }); assert.equal(requests[1].url, 'https://store.example.test/hooks/notify'); await assert.rejects( () => adapters.get('WEBHOOK').send({ ...input, channel: 'WEBHOOK', recipientId: 'http://127.0.0.1/internal' }), (error) => error instanceof NotificationError && error.code === 'NOTIFICATION_ENDPOINT_INVALID' ); const failing = new HttpNotificationAdapter({ endpoint: 'https://gateway.example.test/fail', fetcher: async () => ({ ok: false, status: 503, headers: { get() { return null; } }, async json() { return {}; } }) }); await assert.rejects(() => failing.send(input), (error) => error instanceof NotificationError && error.code === 'NOTIFICATION_PROVIDER_HTTP_ERROR'); console.log('PASS: M10-A configured HTTP adapters enforce HTTPS, idempotency and provider failures.');