{"version":3,"file":"metric-testing.cjs","names":[],"sources":["../src/metric-testing.ts"],"sourcesContent":["/**\n * Testing utilities for Metrics\n *\n * Provides in-memory collection of metrics for testing purposes.\n */\n\nimport type {\n  EventAttributes,\n  FunnelStatus,\n  OutcomeStatus,\n} from './event-subscriber';\n\nexport interface MetricsEvent {\n  event: string;\n  attributes?: EventAttributes;\n  service: string;\n  timestamp: number;\n}\n\nexport interface MetricsFunnelStep {\n  funnel: string;\n  status: FunnelStatus;\n  attributes?: EventAttributes;\n  service: string;\n  timestamp: number;\n}\n\nexport interface MetricsOutcome {\n  operation: string;\n  status: OutcomeStatus;\n  attributes?: EventAttributes;\n  service: string;\n  timestamp: number;\n}\n\nexport interface MetricsValue {\n  metric: string;\n  value: number;\n  attributes?: EventAttributes;\n  service: string;\n  timestamp: number;\n}\n\n/**\n * In-memory metrics collector for testing\n */\nexport interface MetricsCollector {\n  /** Get all collected events */\n  getEvents(): MetricsEvent[];\n  /** Get all collected funnel steps */\n  getFunnelSteps(): MetricsFunnelStep[];\n  /** Get all collected outcomes */\n  getOutcomes(): MetricsOutcome[];\n  /** Get all collected values */\n  getValues(): MetricsValue[];\n  /** Clear all collected metrics */\n  clear(): void;\n  /** Record an event (internal use) */\n  recordEvent(event: MetricsEvent): void;\n  /** Record a funnel step (internal use) */\n  recordFunnelStep(step: MetricsFunnelStep): void;\n  /** Record an outcome (internal use) */\n  recordOutcome(outcome: MetricsOutcome): void;\n  /** Record a value (internal use) */\n  recordValue(value: MetricsValue): void;\n}\n\n/**\n * Create an in-memory metrics collector for testing\n *\n * @example\n * ```typescript\n * const collector = createMetricsCollector()\n *\n * const metrics = new Metric('test-service', { collector })\n * metrics.trackEvent('order.completed', { orderId: '123' })\n *\n * const event =collector.getEvents()\n * expect(events).toHaveLength(1)\n * expect(events[0].event).toBe('order.completed')\n * ```\n */\nexport function createMetricsCollector(): MetricsCollector {\n  const events: MetricsEvent[] = [];\n  const funnelSteps: MetricsFunnelStep[] = [];\n  const outcomes: MetricsOutcome[] = [];\n  const values: MetricsValue[] = [];\n\n  return {\n    getEvents(): MetricsEvent[] {\n      return [...events];\n    },\n\n    getFunnelSteps(): MetricsFunnelStep[] {\n      return [...funnelSteps];\n    },\n\n    getOutcomes(): MetricsOutcome[] {\n      return [...outcomes];\n    },\n\n    getValues(): MetricsValue[] {\n      return [...values];\n    },\n\n    clear(): void {\n      events.length = 0;\n      funnelSteps.length = 0;\n      outcomes.length = 0;\n      values.length = 0;\n    },\n\n    recordEvent(event: MetricsEvent): void {\n      events.push(event);\n    },\n\n    recordFunnelStep(step: MetricsFunnelStep): void {\n      funnelSteps.push(step);\n    },\n\n    recordOutcome(outcome: MetricsOutcome): void {\n      outcomes.push(outcome);\n    },\n\n    recordValue(value: MetricsValue): void {\n      values.push(value);\n    },\n  };\n}\n\n/**\n * Assert that a metric event was tracked\n *\n * @example\n * ```typescript\n * assertEventTracked({\n *   collector,\n *   eventName: 'order.completed',\n *   attributes: { orderId: '123' }\n * })\n * ```\n */\nexport function assertEventTracked(options: {\n  collector: MetricsCollector;\n  eventName: string;\n  attributes?: Record<string, unknown>;\n}): void {\n  const events = options.collector.getEvents();\n  const matching = events.filter((e) => e.event === options.eventName);\n\n  if (matching.length === 0) {\n    throw new Error(`No events found with name: ${options.eventName}`);\n  }\n\n  if (options.attributes) {\n    const matchingWithAttrs = matching.filter((e) =>\n      Object.entries(options.attributes!).every(\n        ([key, value]) => e.attributes && e.attributes[key] === value,\n      ),\n    );\n\n    if (matchingWithAttrs.length === 0) {\n      throw new Error(\n        `Event ${options.eventName} found but attributes don't match: ${JSON.stringify(options.attributes)}`,\n      );\n    }\n  }\n}\n\n/**\n * Assert that an outcome was tracked\n *\n * @example\n * ```typescript\n * assertOutcomeTracked({\n *   collector,\n *   operation: 'payment.process',\n *   status: 'success'\n * })\n * ```\n */\nexport function assertOutcomeTracked(options: {\n  collector: MetricsCollector;\n  operation: string;\n  status: 'success' | 'failure' | 'partial';\n}): void {\n  const outcomes = options.collector.getOutcomes();\n  const matching = outcomes.filter(\n    (o) => o.operation === options.operation && o.status === options.status,\n  );\n\n  if (matching.length === 0) {\n    throw new Error(\n      `No outcomes found with operation: ${options.operation} and status: ${options.status}`,\n    );\n  }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAkFA,SAAgB,yBAA2C;CACzD,MAAM,SAAyB,CAAC;CAChC,MAAM,cAAmC,CAAC;CAC1C,MAAM,WAA6B,CAAC;CACpC,MAAM,SAAyB,CAAC;CAEhC,OAAO;EACL,YAA4B;GAC1B,OAAO,CAAC,GAAG,MAAM;EACnB;EAEA,iBAAsC;GACpC,OAAO,CAAC,GAAG,WAAW;EACxB;EAEA,cAAgC;GAC9B,OAAO,CAAC,GAAG,QAAQ;EACrB;EAEA,YAA4B;GAC1B,OAAO,CAAC,GAAG,MAAM;EACnB;EAEA,QAAc;GACZ,OAAO,SAAS;GAChB,YAAY,SAAS;GACrB,SAAS,SAAS;GAClB,OAAO,SAAS;EAClB;EAEA,YAAY,OAA2B;GACrC,OAAO,KAAK,KAAK;EACnB;EAEA,iBAAiB,MAA+B;GAC9C,YAAY,KAAK,IAAI;EACvB;EAEA,cAAc,SAA+B;GAC3C,SAAS,KAAK,OAAO;EACvB;EAEA,YAAY,OAA2B;GACrC,OAAO,KAAK,KAAK;EACnB;CACF;AACF;;;;;;;;;;;;;AAcA,SAAgB,mBAAmB,SAI1B;CAEP,MAAM,WADS,QAAQ,UAAU,UACX,CAAC,CAAC,QAAQ,MAAM,EAAE,UAAU,QAAQ,SAAS;CAEnE,IAAI,SAAS,WAAW,GACtB,MAAM,IAAI,MAAM,8BAA8B,QAAQ,WAAW;CAGnE,IAAI,QAAQ,YAOV;MAN0B,SAAS,QAAQ,MACzC,OAAO,QAAQ,QAAQ,UAAW,CAAC,CAAC,OACjC,CAAC,KAAK,WAAW,EAAE,cAAc,EAAE,WAAW,SAAS,KAC1D,CAGkB,CAAC,CAAC,WAAW,GAC/B,MAAM,IAAI,MACR,SAAS,QAAQ,UAAU,qCAAqC,KAAK,UAAU,QAAQ,UAAU,GACnG;CACF;AAEJ;;;;;;;;;;;;;AAcA,SAAgB,qBAAqB,SAI5B;CAMP,IALiB,QAAQ,UAAU,YACX,CAAC,CAAC,QACvB,MAAM,EAAE,cAAc,QAAQ,aAAa,EAAE,WAAW,QAAQ,MAGxD,CAAC,CAAC,WAAW,GACtB,MAAM,IAAI,MACR,qCAAqC,QAAQ,UAAU,eAAe,QAAQ,QAChF;AAEJ"}