unleash-server
Version:
Unleash is an enterprise ready feature flag service. It provides different strategies for handling feature flags.
240 lines • 8.85 kB
JavaScript
import { FEATURE_CREATED } from '../events/index.js';
import WebhookAddon from './webhook.js';
import noLogger from '../../test/fixtures/no-logger.js';
import { serializeDates, SYSTEM_USER_ID, } from '../types/index.js';
import { vi } from 'vitest';
import EventEmitter from 'node:events';
import nock from 'nock';
const INTEGRATION_ID = 1337;
beforeEach(() => {
nock.disableNetConnect();
});
afterEach(() => {
nock.cleanAll();
nock.enableNetConnect();
});
const setup = () => {
const registerEventMock = vi.fn();
const addonConfig = {
getLogger: noLogger,
unleashUrl: 'http://some-url.com',
integrationEventsService: {
registerEvent: registerEventMock,
},
flagResolver: {
isEnabled: (expName) => false,
},
eventBus: new EventEmitter(),
};
return {
addon: new WebhookAddon(addonConfig),
registerEventMock,
};
};
describe('Webhook integration', () => {
test('Should handle event without "bodyTemplate"', async () => {
const { addon } = setup();
const event = {
id: 1,
createdAt: new Date(),
createdByUserId: SYSTEM_USER_ID,
type: FEATURE_CREATED,
createdBy: 'some@user.com',
featureName: 'some-toggle',
data: {
name: 'some-toggle',
enabled: false,
strategies: [{ name: 'default' }],
},
};
const parameters = {
url: 'http://test.webhook.com',
};
let callCount = 0;
let callBody;
nock('http://test.webhook.com')
.post('/')
.matchHeader('Content-Type', 'application/json')
.reply(200, (uri, body) => {
callCount++;
callBody = body;
return { ok: true, status: 200 };
});
await addon.handleEvent(event, parameters, INTEGRATION_ID);
expect(callCount).toBe(1);
expect(JSON.stringify(callBody)).toBe(JSON.stringify(event));
expect(nock.isDone()).toBe(true);
});
test('Should format event with "bodyTemplate"', async () => {
const { addon } = setup();
const event = {
id: 1,
createdAt: new Date(),
createdByUserId: SYSTEM_USER_ID,
type: FEATURE_CREATED,
createdBy: 'some@user.com',
featureName: 'some-toggle',
data: {
name: 'some-toggle',
enabled: false,
strategies: [{ name: 'default' }],
},
};
const parameters = {
url: 'http://test.webhook.com/plain',
bodyTemplate: '{{event.type}} on toggle {{event.data.name}}',
contentType: 'text/plain',
};
const expectedBody = 'feature-created on toggle some-toggle';
nock('http://test.webhook.com')
.post('/plain', expectedBody)
.matchHeader('Content-Type', 'text/plain')
.reply(200);
await addon.handleEvent(event, parameters, INTEGRATION_ID);
expect(nock.isDone()).toBe(true);
});
test('should allow for eventJson and eventMarkdown in bodyTemplate', async () => {
const { addon } = setup();
const event = {
id: 1,
createdAt: new Date('2024-07-24T00:00:00.000Z'),
createdByUserId: SYSTEM_USER_ID,
type: FEATURE_CREATED,
createdBy: 'some@user.com',
featureName: 'some-toggle',
project: 'default',
data: {
name: 'some-toggle',
enabled: false,
strategies: [{ name: 'default' }],
},
};
const parameters = {
url: 'http://test.webhook.com/plain',
bodyTemplate: '{\n "json": {{{eventJson}}},\n "markdown": "{{eventMarkdown}}"\n}',
contentType: 'text/plain',
};
let callBody;
nock('http://test.webhook.com')
.post('/plain')
.matchHeader('Content-Type', 'text/plain')
.reply(200, (uri, body) => {
callBody = body;
return {
status: 200,
body: 'ok',
};
});
await addon.handleEvent(event, parameters, INTEGRATION_ID);
expect(callBody).toMatchSnapshot();
expect(JSON.parse(JSON.parse(callBody).json)).toEqual(serializeDates(event));
expect(nock.isDone()).toBe(true);
});
test('Should format event with "authorization"', async () => {
const { addon } = setup();
const event = {
id: 1,
createdAt: new Date(),
createdByUserId: SYSTEM_USER_ID,
type: FEATURE_CREATED,
createdBy: 'some@user.com',
featureName: 'some-toggle',
data: {
name: 'some-toggle',
enabled: false,
strategies: [{ name: 'default' }],
},
};
const parameters = {
url: 'http://test.webhook.com/plain',
bodyTemplate: '{{event.type}} on toggle {{event.data.name}}',
contentType: 'text/plain',
authorization: 'API KEY 123abc',
};
const expectedBody = 'feature-created on toggle some-toggle';
nock('http://test.webhook.com')
.post('/plain', expectedBody)
.matchHeader('Content-Type', 'text/plain')
.matchHeader('Authorization', 'API KEY 123abc')
.reply(200);
await addon.handleEvent(event, parameters, INTEGRATION_ID);
expect(nock.isDone()).toBe(true);
});
test('Should handle custom headers', async () => {
const { addon } = setup();
const event = {
id: 1,
createdAt: new Date(),
createdByUserId: SYSTEM_USER_ID,
type: FEATURE_CREATED,
createdBy: 'some@user.com',
featureName: 'some-toggle',
data: {
name: 'some-toggle',
enabled: false,
strategies: [{ name: 'default' }],
},
};
const parameters = {
url: 'http://test.webhook.com/plain',
bodyTemplate: '{{event.type}} on toggle {{event.data.name}}',
contentType: 'text/plain',
authorization: 'API KEY 123abc',
customHeaders: `{ "MY_CUSTOM_HEADER": "MY_CUSTOM_VALUE" }`,
};
const expectedBody = 'feature-created on toggle some-toggle';
nock('http://test.webhook.com')
.post('/plain', expectedBody)
.matchHeader('Content-Type', 'text/plain')
.matchHeader('Authorization', 'API KEY 123abc')
.matchHeader('MY_CUSTOM_HEADER', 'MY_CUSTOM_VALUE')
.reply(200);
await addon.handleEvent(event, parameters, INTEGRATION_ID);
expect(nock.isDone()).toBe(true);
});
test('Should call registerEvent', async () => {
const { addon, registerEventMock } = setup();
const event = {
id: 1,
createdAt: new Date(),
createdByUserId: SYSTEM_USER_ID,
type: FEATURE_CREATED,
createdBy: 'some@user.com',
featureName: 'some-toggle',
data: {
name: 'some-toggle',
enabled: false,
strategies: [{ name: 'default' }],
},
};
const parameters = {
url: 'http://test.webhook.com/plain',
bodyTemplate: '{{event.type}} on toggle {{event.data.name}}',
contentType: 'text/plain',
authorization: 'API KEY 123abc',
customHeaders: `{ "MY_CUSTOM_HEADER": "MY_CUSTOM_VALUE" }`,
};
const expectedBody = 'feature-created on toggle some-toggle';
nock('http://test.webhook.com')
.post('/plain', expectedBody)
.matchHeader('Content-Type', 'text/plain')
.matchHeader('Authorization', 'API KEY 123abc')
.matchHeader('MY_CUSTOM_HEADER', 'MY_CUSTOM_VALUE')
.reply(200);
await addon.handleEvent(event, parameters, INTEGRATION_ID);
expect(registerEventMock).toHaveBeenCalledTimes(1);
expect(registerEventMock).toHaveBeenCalledWith({
integrationId: INTEGRATION_ID,
state: 'success',
stateDetails: 'Webhook request was successful with status code: 200.',
event: serializeDates(event),
details: {
url: parameters.url,
contentType: parameters.contentType,
body: expectedBody,
},
});
expect(nock.isDone()).toBe(true);
});
});
//# sourceMappingURL=webhook.test.js.map