Enables outbound PSTN probes via TwiML webhooks with Webex result cards, status polling, and optional store CDR enrichment.
97 lines
3.8 KiB
JavaScript
97 lines
3.8 KiB
JavaScript
// tests/callTest.signature.test.js
|
|
|
|
import test from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import crypto from 'node:crypto';
|
|
|
|
import twilio from 'twilio';
|
|
|
|
import { validateTwilioSignature } from '../integrations/twilio/client.js';
|
|
import { resolveCallTestWebhookUrl } from '../services/callTest/config.js';
|
|
|
|
test('validateTwilioSignature matches Twilio HMAC algorithm', () => {
|
|
const authToken = 'test-auth-token';
|
|
const url = 'https://example.com/twilio/calltest/status?testId=abc';
|
|
const params = { CallStatus: 'completed', CallSid: 'CA123' };
|
|
|
|
let data = url;
|
|
for (const key of Object.keys(params).sort()) {
|
|
data += key + params[key];
|
|
}
|
|
const signature = crypto.createHmac('sha1', authToken).update(data, 'utf-8').digest('base64');
|
|
|
|
const prevSid = process.env.TWILIO_ACCOUNT_SID;
|
|
const prevToken = process.env.TWILIO_AUTH_TOKEN;
|
|
const prevFrom = process.env.TWILIO_FROM_NUMBER;
|
|
const prevBase = process.env.TWILIO_WEBHOOK_BASE_URL;
|
|
|
|
process.env.TWILIO_ACCOUNT_SID = 'ACtest';
|
|
process.env.TWILIO_AUTH_TOKEN = authToken;
|
|
process.env.TWILIO_FROM_NUMBER = '+15550001111';
|
|
process.env.TWILIO_WEBHOOK_BASE_URL = 'https://example.com';
|
|
|
|
try {
|
|
assert.equal(validateTwilioSignature(signature, url, params), true);
|
|
assert.equal(validateTwilioSignature('bad', url, params), false);
|
|
} finally {
|
|
if (prevSid == null) delete process.env.TWILIO_ACCOUNT_SID;
|
|
else process.env.TWILIO_ACCOUNT_SID = prevSid;
|
|
if (prevToken == null) delete process.env.TWILIO_AUTH_TOKEN;
|
|
else process.env.TWILIO_AUTH_TOKEN = prevToken;
|
|
if (prevFrom == null) delete process.env.TWILIO_FROM_NUMBER;
|
|
else process.env.TWILIO_FROM_NUMBER = prevFrom;
|
|
if (prevBase == null) delete process.env.TWILIO_WEBHOOK_BASE_URL;
|
|
else process.env.TWILIO_WEBHOOK_BASE_URL = prevBase;
|
|
}
|
|
});
|
|
|
|
test('resolveCallTestWebhookUrl rebuilds the registered Twilio voice URL', () => {
|
|
const prevBase = process.env.TWILIO_WEBHOOK_BASE_URL;
|
|
process.env.TWILIO_WEBHOOK_BASE_URL = 'https://proxy.example.com/CollabSupport';
|
|
|
|
try {
|
|
const req = {
|
|
path: '/twilio/calltest/voice',
|
|
originalUrl: '/twilio/calltest/voice?testId=abc&mode=dial&step=intro',
|
|
query: { testId: 'abc', mode: 'dial', step: 'intro' },
|
|
};
|
|
assert.equal(
|
|
resolveCallTestWebhookUrl(req),
|
|
'https://proxy.example.com/CollabSupport/twilio/calltest/voice?testId=abc&mode=dial&step=intro',
|
|
);
|
|
} finally {
|
|
if (prevBase == null) delete process.env.TWILIO_WEBHOOK_BASE_URL;
|
|
else process.env.TWILIO_WEBHOOK_BASE_URL = prevBase;
|
|
}
|
|
});
|
|
|
|
test('validateTwilioSignature accepts array POST params like Twilio SDK', () => {
|
|
const authToken = 'test-auth-token';
|
|
const url = 'https://example.com/twilio/calltest/status?testId=abc';
|
|
const params = { Tags: ['a', 'b'], CallStatus: 'completed' };
|
|
|
|
const signature = twilio.getExpectedTwilioSignature(authToken, url, params);
|
|
|
|
const prevSid = process.env.TWILIO_ACCOUNT_SID;
|
|
const prevToken = process.env.TWILIO_AUTH_TOKEN;
|
|
const prevFrom = process.env.TWILIO_FROM_NUMBER;
|
|
const prevBase = process.env.TWILIO_WEBHOOK_BASE_URL;
|
|
|
|
process.env.TWILIO_ACCOUNT_SID = 'ACtest';
|
|
process.env.TWILIO_AUTH_TOKEN = authToken;
|
|
process.env.TWILIO_FROM_NUMBER = '+15550001111';
|
|
process.env.TWILIO_WEBHOOK_BASE_URL = 'https://example.com';
|
|
|
|
try {
|
|
assert.equal(validateTwilioSignature(signature, url, params), true);
|
|
} finally {
|
|
if (prevSid == null) delete process.env.TWILIO_ACCOUNT_SID;
|
|
else process.env.TWILIO_ACCOUNT_SID = prevSid;
|
|
if (prevToken == null) delete process.env.TWILIO_AUTH_TOKEN;
|
|
else process.env.TWILIO_AUTH_TOKEN = prevToken;
|
|
if (prevFrom == null) delete process.env.TWILIO_FROM_NUMBER;
|
|
else process.env.TWILIO_FROM_NUMBER = prevFrom;
|
|
if (prevBase == null) delete process.env.TWILIO_WEBHOOK_BASE_URL;
|
|
else process.env.TWILIO_WEBHOOK_BASE_URL = prevBase;
|
|
}
|
|
});
|