/** @jest-environment jsdom */ jest.mock('../../sinks/datadog', () => ({ sendToDatadog: jest.fn(), })); import { resetJourney } from '../../core'; import { moduleRuntime } from '../../core/runtime'; import type { JourneyEvent } from '../../core/types'; import { sendToConsole } from '../../sinks/console'; import { sendToDatadog } from '../../sinks/datadog'; describe('[journey] moduleRuntime sinks', () => { let payload: JourneyEvent; beforeEach(() => { jest.mocked(sendToDatadog).mockClear(); resetJourney({ sinks: [sendToDatadog] }); payload = { journey: { name: 'test', team: 't', group: 'g', service: 's', outcome: 'good', durationMs: 1, steps: [], }, }; }); afterEach(() => { resetJourney({ sinks: [sendToDatadog, sendToConsole] }); }); const subject = () => moduleRuntime.emit(payload); test('forwards the payload to each configured sink', () => { subject(); expect(sendToDatadog).toHaveBeenCalledWith(payload); }); describe('with an additional sink', () => { let extra: jest.Mock; beforeEach(() => { extra = jest.fn(); moduleRuntime.addSink(extra); }); test('invokes every configured sink', () => { subject(); expect(sendToDatadog).toHaveBeenCalledWith(payload); expect(extra).toHaveBeenCalledWith(payload); }); test('continues to later sinks when one throws', () => { moduleRuntime.setSinks([ () => { throw new Error('boom'); }, sendToDatadog, extra, ]); expect(() => subject()).not.toThrow(); expect(sendToDatadog).toHaveBeenCalledWith(payload); expect(extra).toHaveBeenCalledWith(payload); }); }); describe('when sinks are replaced', () => { let only: jest.Mock; beforeEach(() => { only = jest.fn(); moduleRuntime.setSinks([only]); }); test('does not call the previous sinks', () => { subject(); expect(only).toHaveBeenCalledWith(payload); expect(sendToDatadog).not.toHaveBeenCalled(); }); }); describe('with an empty sink list', () => { beforeEach(() => { moduleRuntime.setSinks([]); }); test('emits nowhere', () => { subject(); expect(sendToDatadog).not.toHaveBeenCalled(); }); }); });