5.6 KiB
ADDED Requirements
Requirement: Image policy
The @suaveplan/testing-integration-otel-collector package SHALL launch the otel/opentelemetry-collector-contrib container pinned to a specific minor version (e.g. 0.<minor>). A digest-pin migration MUST be tracked as a follow-up task; bare latest tags are forbidden.
Scenario: Tag pin enforced
- WHEN the fixture is constructed without a config override
- THEN the resolved image string MUST match
otel/opentelemetry-collector-contrib:0.<minor>AND MUST NOT equalotel/opentelemetry-collector-contrib:latest
Scenario: Image override accepted
- WHEN the fixture constructor is given
{ image: 'otel/opentelemetry-collector-contrib:0.99.0@sha256:...' } - THEN the launched container uses the supplied digest-pinned reference verbatim
Requirement: Env-bridge contract
The fixture SHALL set OTEL_EXPORTER_OTLP_ENDPOINT and OTEL_EXPORTER_OTLP_PROTOCOL (http/protobuf by default, grpc when the config requests otlp-grpc) on the host process during setup(), and MAY set OTEL_EXPORTER_OTLP_HEADERS when the config supplies headers. All values MUST be restored to their prior state on teardown().
Scenario: Endpoint published on setup
- WHEN
setup()resolves - THEN
process.env.OTEL_EXPORTER_OTLP_ENDPOINTis a URL pointing at the running collector's OTLP port ANDprocess.env.OTEL_EXPORTER_OTLP_PROTOCOL === 'http/protobuf'
Scenario: Prior env-state restored on teardown
- WHEN
OTEL_EXPORTER_OTLP_ENDPOINTwas set to'http://prior'beforesetup()andteardown()later runs - THEN
process.env.OTEL_EXPORTER_OTLP_ENDPOINT === 'http://prior'afterteardown()resolves
Requirement: Health-check contract
The fixture SHALL consider the collector ready only when an HTTP GET on the collector's :13133/health/status endpoint (port configurable) returns 200 within the configured timeout (default 60 s). Health polling MUST use the HealthPoller from @suaveplan/testing-integration.
Scenario: Health endpoint returns 200
- WHEN the collector is fully started AND the health endpoint returns HTTP 200
- THEN
setup()resolves ANDgetSpans()becomes callable
Scenario: Health timeout exceeded
- WHEN the health endpoint never returns 200 within the configured timeout
- THEN
setup()rejects withIntegrationErrorwhosecode === "INTEGRATION.OTEL_COLLECTOR.HEALTH_TIMEOUT"AND whosecontext.timeoutMsmatches the configured timeout
Scenario: Injectable fetch for unit-testing the fixture
- WHEN the fixture is constructed with
{ fetchFn } - THEN all health-check requests MUST use the supplied
fetchFnAND MUST NOT touch the globalfetch
Requirement: Config shape and synthesis
The fixture config object SHALL conform to { receivers: ('otlp-grpc' | 'otlp-http')[]; exporters: ('logging' | 'memory' | 'jaeger' | 'file')[]; configFile?: string }. When configFile is omitted the fixture MUST synthesise a minimal otelcol-config.yaml from the receivers and exporters lists and mount it into the container. When configFile is supplied the fixture MUST mount that file verbatim and MUST NOT synthesise.
Scenario: Synthesised config wires the requested receivers and exporters
- WHEN
setup({ receivers: ['otlp-http'], exporters: ['memory'] })runs - THEN the mounted
otelcol-config.yamldeclares an OTLP HTTP receiver AND an in-memory exporter AND a single pipeline routing the receiver to the exporter
Scenario: External config file is mounted verbatim
- WHEN
setup({ receivers: [], exporters: [], configFile: '/abs/path/custom.yaml' })runs - THEN the container's
/etc/otelcol-contrib/config.yamlis the byte-identical contents of/abs/path/custom.yamlAND no synthesis occurs
Requirement: Span query helper
The fixture SHALL expose getSpans({ filter }) which returns ReadableSpan[] from the collector's in-memory exporter. The helper MUST throw IntegrationError("INTEGRATION.OTEL_COLLECTOR.MEMORY_EXPORTER_NOT_CONFIGURED", …) when the active config does not include the memory exporter.
Scenario: Returns spans matching filter
- WHEN a producer has emitted spans named
op.fooandop.barANDgetSpans({ filter: span => span.name === 'op.foo' })is called - THEN the result contains every
op.foospan AND noop.barspans
Scenario: Helper unavailable without memory exporter
- WHEN the fixture was started with
exporters: ['logging']ANDgetSpans()is called - THEN the call throws
IntegrationErrorwithcode === "INTEGRATION.OTEL_COLLECTOR.MEMORY_EXPORTER_NOT_CONFIGURED"
Requirement: Error code prefix
Every error thrown by the package SHALL be an IntegrationError (or subclass) whose code begins with INTEGRATION.OTEL_COLLECTOR.. Plain Error / TypeError MUST NOT be thrown from any public code path.
Scenario: Code namespace enforced
- WHEN any public method on the fixture throws
- THEN the thrown value
instanceof IntegrationError === trueANDerror.code.startsWith("INTEGRATION.OTEL_COLLECTOR.") === true
Requirement: Coverage gate
Istanbul statement, branch, function, and line coverage across packages/testing/testing-integration-otel-collector/src/ (excluding *.bench.ts and *.schemas.ts) MUST be 100%. The pre-publish gate (bunx turbo test:coverage --filter=@suaveplan/testing-integration-otel-collector) MUST hard-fail below 100%.
Scenario: Coverage gate trips below 100%
- WHEN any line, branch, function, or statement is uncovered
- THEN the pre-publish gate fails AND the package MUST NOT be published