Skip to content

test: the conformance matrix cannot reach nuxt, nitro or nitro/v3 #487

Description

@HugoRCD

The gap

src/shared/conformance.ts encodes the behaviours every framework integration must share, and describeStandardHttpMatrix drives them. It covers 10 integrations:

hono · express · elysia · fastify · nestjs · orpc · react-router · sveltekit · next · workers

It does not cover evlog/nuxt, evlog/nitro or evlog/nitro/v3 — arguably the most important ones for this project.

Why it is structural, not an oversight

The mount contract injects the drain as a function:

export type ConformanceMount = (options: BaseEvlogOptions) => ConformanceApp | Promise<ConformanceApp>

That works for anything configured per request. But Nitro receives its drain through the evlog:drain hook inside a built app — and a function cannot cross a build boundary. Driving Nitro through this contract would mean writing the drain into a fixture's source and rebuilding per check, which is far too slow for a per-check mount.

Today those integrations rely on their own fixture-based tests (test/nitro/, test/nitro-v3/) plus direct unit tests of internals like callEnrichAndDrain. Those are real tests — the point is only that they are not the shared contract, so nothing guarantees Nitro and Hono behave identically for include / exclude / routes / enrich ordering.

This matters because the matrix is what caught two real regressions: evlog/workers honouring only cf-ray for the request id (#472), and evlog/next accepting plugins without ever applying them (#474). Nuxt and Nitro get no such safety net.

Possible approach

A second, config-based mount mode:

  • the fixture declares a drain that writes to a known sink (a file, or an in-process HTTP endpoint the suite owns)
  • the mount returns a readEvents() alongside fire(), instead of the suite injecting a collector
  • checks that need include / exclude / routes pass them through the fixture's nitro.config.ts / module options rather than as middleware options

That means splitting ConformanceCheck into "drive the request" and "read what was drained", so the same behavioural assertions run against either mount style. Build cost can be amortised by building the fixture once per suite rather than per check.

Related

src/shared/conformance.ts is deliberately not exported from evlog/toolkit today, partly for this reason — publishing it as "the contract every integration satisfies" would be inaccurate while the flagship integrations are outside it. The module header documents the exclusion.

A second blocker for any future public export, worth solving alongside: the suite cannot distinguish "your mount is wrong" from "your integration breaks the contract". A mount that serves a 404 is currently reported as a conformance failure. A preflight sanity check — assert the route answers 200 without evlog mounted — would fix that.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions