Files
jobqueue/tests/WebhookDispatcher.test.ts

76 lines
2.1 KiB
TypeScript

import { createServer } from 'node:http';
import { WebhookDispatcher } from '../src/index.js';
describe('WebhookDispatcher', () => {
it('delivers signed webhook payloads', async () => {
const payloads: string[] = [];
const headers: string[] = [];
const server = createServer((request, response) => {
let body = '';
request.on('data', (chunk) => {
body += chunk.toString();
});
request.on('end', () => {
payloads.push(body);
headers.push(String(request.headers['x-jobqueue-signature']));
response.writeHead(202).end();
});
});
await new Promise<void>((resolve) => {
server.listen(0, '127.0.0.1', () => resolve());
});
const address = server.address();
if (!address || typeof address === 'string') {
throw new Error('Server address unavailable');
}
const dispatcher = new WebhookDispatcher({
url: `http://127.0.0.1:${address.port}/hook`,
secret: 'top-secret',
events: ['job:completed'],
});
try {
const result = await dispatcher.dispatch('job:completed', {
id: 'job-1',
status: 'completed',
data: { url: 'https://example.com' },
currentPhase: null,
phases: [],
phaseResults: {},
progress: 100,
progressMessage: null,
error: null,
retryCount: 0,
maxAttempts: 1,
webhookUrl: null,
webhookSent: false,
createdAt: new Date().toISOString(),
startedAt: null,
completedAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
scheduledAt: null,
cancelledAt: null,
});
expect(result.status).toBe(202);
expect(payloads).toHaveLength(1);
expect(payloads[0]).toContain('"event":"job:completed"');
expect(headers[0]).toMatch(/^[a-f0-9]{64}$/);
} finally {
await new Promise<void>((resolve, reject) => {
server.close((error) => {
if (error) {
reject(error);
return;
}
resolve();
});
});
}
});
});