"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.baseWebhookTests = void 0;
const nock_1 = __importDefault(require("nock"));
const actions_core_1 = require("@segment/actions-core");
const index_1 = __importDefault(require("../index"));
const crypto_1 = require("crypto");
const baseWebhookTests = (def) => {
    const testDestination = (0, actions_core_1.createTestIntegration)(def);
    describe(def.name, () => {
        describe('send', () => {
            it('should work with default mapping', async () => {
                const url = 'https://example.com';
                const event = (0, actions_core_1.createTestEvent)();
                (0, nock_1.default)(url)
                    .post('/', event)
                    .reply(200);
                const responses = await testDestination.testAction('send', {
                    event,
                    mapping: {
                        url
                    },
                    useDefaultMappings: true
                });
                expect(responses.length).toBe(1);
                expect(responses[0].status).toBe(200);
            });
            it('supports customizations', async () => {
                const url = 'https://example.build';
                const event = (0, actions_core_1.createTestEvent)();
                const headerField = 'Custom-Header';
                const headerValue = 'Custom-Value';
                const data = { cool: true };
                (0, nock_1.default)(url).put('/', data).matchHeader(headerField, headerValue).reply(200);
                const responses = await testDestination.testAction('send', {
                    event,
                    mapping: {
                        url,
                        method: 'PUT',
                        headers: { [headerField]: headerValue },
                        data
                    }
                });
                expect(responses.length).toBe(1);
                expect(responses[0].status).toBe(200);
            });
            it('supports request signing', async () => {
                const url = 'https://example.com';
                const event = (0, actions_core_1.createTestEvent)({
                    properties: { cool: true }
                });
                const payload = JSON.stringify(event.properties);
                const sharedSecret = 'abc123';
                (0, nock_1.default)(url)
                    .post('/', payload)
                    .reply(async function (_uri, body) {
                    const bodyString = JSON.stringify(body);
                    const expectSignature = this.req.headers['x-signature'][0];
                    const actualSignature = (0, crypto_1.createHmac)('sha1', sharedSecret).update(bodyString).digest('hex');
                    if (expectSignature.length !== actualSignature.length ||
                        !(0, crypto_1.timingSafeEqual)(Buffer.from(actualSignature, 'hex'), Buffer.from(expectSignature, 'hex'))) {
                        return [400, 'Invalid signature'];
                    }
                    return [200, 'OK'];
                });
                const responses = await testDestination.testAction('send', {
                    event,
                    mapping: {
                        url,
                        data: { '@path': '$.properties' }
                    },
                    settings: { sharedSecret },
                    useDefaultMappings: true
                });
                expect(responses.length).toBe(1);
                expect(responses[0].status).toBe(200);
            });
            it('supports request signing with batched events', async () => {
                const url = 'https://example.com';
                const events = [
                    (0, actions_core_1.createTestEvent)({
                        properties: { cool: false }
                    }),
                    (0, actions_core_1.createTestEvent)({
                        properties: { cool: true }
                    })
                ];
                const payload = JSON.stringify(events.map(({ properties }) => properties));
                const sharedSecret = 'abc123';
                (0, nock_1.default)(url)
                    .post('/', payload)
                    .reply(async function (_uri, body) {
                    const expectSignature = this.req.headers['x-signature'][0];
                    const actualSignature = (0, crypto_1.createHmac)('sha1', sharedSecret).update(JSON.stringify(body[0])).digest('hex');
                    if (expectSignature.length !== actualSignature.length ||
                        !(0, crypto_1.timingSafeEqual)(Buffer.from(actualSignature, 'hex'), Buffer.from(expectSignature, 'hex'))) {
                        return [400, 'Invalid signature123'];
                    }
                    return [200, 'OK'];
                });
                const responses = await testDestination.testBatchAction('send', {
                    events,
                    mapping: {
                        url,
                        data: { '@path': '$.properties' }
                    },
                    settings: { sharedSecret },
                    useDefaultMappings: true
                });
                expect(responses.length).toBe(1);
                expect(responses[0].status).toBe(200);
            });
            it('should throw an error when header value is invalid', async () => {
                const url = 'https://example.build';
                const event = (0, actions_core_1.createTestEvent)();
                const headerField = 'Custom-Header';
                const headerValue = 'هيثم';
                const data = { cool: true };
                (0, nock_1.default)(url)
                    .put('/', data)
                    .matchHeader(headerField, headerValue)
                    .replyWithError('TypeError: هيثم is not a legal HTTP header value');
                await expect(testDestination.testAction('send', {
                    event,
                    mapping: {
                        url,
                        method: 'PUT',
                        headers: { [headerField]: headerValue },
                        data
                    }
                })).rejects.toThrow(actions_core_1.PayloadValidationError);
            });
            it('should incr stats by unique url, headers and method count', async () => {
                const testEvent1 = {
                    properties: {
                        url: 'https://example.build',
                        method: 'POST',
                        headers: {
                            'sample-header': 'value1'
                        }
                    }
                };
                const testEvent2 = {
                    properties: {
                        url: 'https://example.build',
                        method: 'PUT',
                        headers: {
                            'sample-header': 'value1'
                        }
                    }
                };
                const events = [(0, actions_core_1.createTestEvent)(testEvent1), (0, actions_core_1.createTestEvent)(testEvent2)];
                (0, nock_1.default)(testEvent1.properties.url).post('/').reply(200, { success: true });
                const statsClient = {
                    incr: jest.fn(),
                    observe: jest.fn(),
                    _name: jest.fn(),
                    _tags: jest.fn(),
                    set: jest.fn,
                    histogram: jest.fn()
                };
                const statsContext = {
                    statsClient,
                    tags: ['test:tag']
                };
                const responses = await testDestination.testBatchAction('send', {
                    events,
                    mapping: {
                        url: {
                            '@path': '$.properties.url'
                        },
                        method: {
                            '@path': '$.properties.method'
                        },
                        headers: {
                            'sample-header': {
                                '@path': '$.properties.sample-header'
                            }
                        }
                    },
                    useDefaultMappings: true,
                    statsContext
                });
                expect(responses.length).toBe(1);
                expect(responses[0].status).toBe(200);
                expect(statsClient.histogram).toHaveBeenCalledWith('webhook.configurable_batch_keys.unique_keys', 2, statsContext.tags);
            });
        });
        it('should have batch keys default to url, method, headers', () => {
            const action = testDestination.definition.actions.send;
            expect(action.fields.batch_keys).toBeDefined();
            expect(action.fields.batch_keys?.default).toBeDefined();
            expect(action.fields.batch_keys?.default).toEqual(['url', 'method', 'headers']);
        });
    });
};
exports.baseWebhookTests = baseWebhookTests;
(0, exports.baseWebhookTests)(index_1.default);
//# sourceMappingURL=webhook.test.js.map