d70c7ea47b
Contract (capability incl. requiresFollowupFetch seam, verifySignature, normalize, fetch?, send), HMAC-SHA256 sign/verify (timing-safe), reference WebhookAdapter (normalize→IngestInteractionRequest), SandboxSink (no network), email/whatsapp fixtures. CJS build (consumed by the NestJS service). 4 tests; boundary updated. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
37 lines
1.6 KiB
TypeScript
37 lines
1.6 KiB
TypeScript
import { describe, it, expect } from 'vitest';
|
|
import { WebhookAdapter, hmacSign, hmacVerify, signedFixture, emailFixture } from './index';
|
|
|
|
describe('iios-adapter-sdk', () => {
|
|
const secret = 'shh';
|
|
const adapter = new WebhookAdapter('WEBHOOK');
|
|
|
|
it('hmac verify: accepts a good sig, rejects tampered/absent', () => {
|
|
const body = JSON.stringify({ a: 1 });
|
|
const sig = hmacSign(body, secret);
|
|
expect(hmacVerify(body, secret, sig)).toBe(true);
|
|
expect(hmacVerify(body + 'x', secret, sig)).toBe(false);
|
|
expect(hmacVerify(body, secret, undefined)).toBe(false);
|
|
});
|
|
|
|
it('verifySignature reads x-iios-signature', () => {
|
|
const { body, headers } = signedFixture(emailFixture, secret);
|
|
expect(adapter.verifySignature(body, headers, secret)).toBe(true);
|
|
expect(adapter.verifySignature(body, { 'x-iios-signature': 'sha256=bad' }, secret)).toBe(false);
|
|
});
|
|
|
|
it('normalize maps a provider payload into a valid ingest request', () => {
|
|
const req = adapter.normalize(emailFixture, { scope: { orgId: 'o', appId: 'a' } });
|
|
expect(req.source.handleKind).toBe('EXTERNAL_VISITOR');
|
|
expect(req.source.externalId).toBe(emailFixture.from);
|
|
expect(req.parts[0]?.bodyText).toBe(emailFixture.text);
|
|
expect(req.providerEventId).toBe(emailFixture.eventId);
|
|
expect(req.thread?.externalThreadId).toBe(emailFixture.threadRef);
|
|
});
|
|
|
|
it('send goes to the sandbox (no network)', async () => {
|
|
const r = await adapter.send({ channelType: 'WEBHOOK', target: 'x', payload: { text: 'hi' } });
|
|
expect(r.outcome).toBe('SENT');
|
|
expect(r.providerRef).toContain('sim-');
|
|
});
|
|
});
|