Ctrl K
ComunidadGuías…

voice-transcription/webhook.delivery.test.ts

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
import { test } from 'node:test';
import assert from 'node:assert/strict';
import { createHmac } from 'node:crypto';
import type { PluginNetCapability, PluginNetRequestInit, PluginNetResponse } from '../types/openwa';
import { WebhookDelivery, TranscriptionPayload } from './webhook.delivery.ts';

function res(partial: { ok?: boolean; status?: number }): PluginNetResponse {
  return {
    ok: partial.ok ?? true,
    status: partial.status ?? 200,
    statusText: '',
    headers: {},
    body: '',
  };
}

function fakeNet(response: PluginNetResponse) {
  const calls: Array<{ url: string; init: PluginNetRequestInit }> = [];
  const net: PluginNetCapability = {
    fetch: async (url: string, init?: PluginNetRequestInit) => {
      calls.push({ url, init: init ?? {} });
      return response;
    },
  };
  return { net, calls };
}

const payload: TranscriptionPayload = {
  event: 'message.transcription',
  sessionId: 's1',
  messageId: 'm1',
  chatId: 'c1@s.whatsapp.net',
  status: 'completed',
  source: 'speech-to-text',
  untrusted: true,
  transcription: { text: 'hola mundo', language: 'es', provider: 'faster-whisper', model: 'small' },
};

test('POSTs the payload as JSON to the configured url', async () => {
  const { net, calls } = fakeNet(res({}));
  await new WebhookDelivery({ url: 'http://hook.local/in', timeoutMs: 5000, net }).deliver(payload);
  assert.equal(calls[0].url, 'http://hook.local/in');
  assert.equal(calls[0].init.method, 'POST');
  assert.equal(calls[0].init.headers!['content-type'], 'application/json');
  assert.deepEqual(JSON.parse(calls[0].init.body as string), payload);
});

test('signs the body with HMAC-SHA256 in X-OpenWA-Signature when a secret is configured', async () => {
  const { net, calls } = fakeNet(res({}));
  await new WebhookDelivery({ url: 'http://hook.local/in', secret: 'shh', timeoutMs: 5000, net }).deliver(payload);
  const sentBody = calls[0].init.body as string;
  const expected = `sha256=${createHmac('sha256', 'shh').update(sentBody).digest('hex')}`;
  assert.equal(calls[0].init.headers!['X-OpenWA-Signature'], expected);
  assert.equal(calls[0].init.headers!['authorization'], undefined); // bearer replaced by the signature
});

test('omits the signature header when no secret is configured', async () => {
  const { net, calls } = fakeNet(res({}));
  await new WebhookDelivery({ url: 'http://hook.local/in', timeoutMs: 5000, net }).deliver(payload);
  assert.equal(calls[0].init.headers!['X-OpenWA-Signature'], undefined);
});

test('throws on a non-ok status so the caller can log the miss', async () => {
  const { net } = fakeNet(res({ ok: false, status: 502 }));
  await assert.rejects(
    new WebhookDelivery({ url: 'http://hook.local/in', timeoutMs: 5000, net }).deliver(payload),
    /502/,
  );
});