Skip to content

test: cover orpc and next with the shared middleware conformance matrix - #479

Closed
HugoRCD wants to merge 1 commit into
mainfrom
feat/integration-conformance-suite
Closed

test: cover orpc and next with the shared middleware conformance matrix#479
HugoRCD wants to merge 1 commit into
mainfrom
feat/integration-conformance-suite

Conversation

@HugoRCD

@HugoRCD HugoRCD commented Aug 1, 2026

Copy link
Copy Markdown
Owner

Why

The contract every framework integration shares lived only in this repo's Vitest helper (describeStandardHttpMatrix). Two consequences:

  • a community integration had no way to check itself against it
  • nothing stopped a built-in from quietly dropping part of it

That is not hypothetical. Both of these were found by pointing this matrix at code that had drifted:

What

src/shared/conformance.ts re-expresses the specs as plain async checks that throw on failure, with no test-framework dependency:

import { runIntegrationConformance } from 'evlog/toolkit'

const results = await runIntegrationConformance((options) => {
  const app = createMyApp()
  app.use(evlog(options))
  app.get('/api/users', () => ({ users: [] }))
  return { fire: async ({ method, path, headers }) => ({ status: (await app.handle(...)).status }) }
})

Exported as integrationConformanceChecks (the list) and runIntegrationConformance() (runner returning per-check results). describeStandardHttpMatrix is now a thin Vitest binding over the same list — the repo and the community assert identical behaviour, not two copies that can drift.

The contract

Check What it catches
Emits method, path, status, level, duration the wide event never reaches the drain
Reuses an inbound x-request-id traces break across service hops
Applies per-route routes service overrides routes silently ignored
Skips routes matched by exclude — but still serves them filtered routes still logged, or worse, not served
Runs enrich before drain, with the response status enricher output missing from drained events

The last two are new relative to the old matrix.

Coverage

evlog/orpc and evlog/next join the matrix — both pass unmodified, which is the result I wanted: they had the behaviour, it just was not pinned.

Coverage is now hono, express, elysia, fastify, nestjs, react-router, sveltekit, orpc, next (+ workers via #472). evlog/eve stays out — it is turn-based, not HTTP.

Notes

Writing the suite surfaced that event.duration is the human-formatted string the logger writes ("2ms"), not a number. The check asserts presence rather than type; worth knowing if you consume duration downstream expecting milliseconds.

Docs: new "Verify your integration" section on the custom-framework page, with both the standalone runner and the Vitest binding.

Verification

  • pnpm run test — 1652/1652 pass; full suite run twice back to back plus the framework subset three times, no flakes
  • Confirmed no framework test uses vi.useFakeTimers(), so the suite's poll-based waitFor cannot deadlock against them
  • pnpm run lint — 0 errors (2 pre-existing max-params warnings in nitro-v3/plugin.ts)
  • pnpm run typecheck — 26/26 tasks pass
  • pnpm run api:snapshot — diff is + integrationConformanceChecks, + runIntegrationConformance

Based directly on main, independent of the other open PRs.

Summary by CodeRabbit

  • Bug Fixes

    • Improved request ID handling for Workers integrations.
    • Fixed Next.js plugin application behavior.
    • Added checks for excluded routes and enrichment before event draining.
  • Tests

    • Expanded integration conformance coverage across oRPC and Next.js.
    • Standardized checks for event fields, request IDs, route service overrides, and HTTP responses.

@vercel

vercel Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
evlog-docs Ready Ready Preview, v0 Aug 1, 2026 5:42pm
evlog-render-lab Ready Ready Preview Aug 1, 2026 5:42pm
evlog-telemetry Ready Ready Preview Aug 1, 2026 5:42pm
just-use-evlog Ready Ready Preview Aug 1, 2026 5:42pm

Request Review

@changeset-bot

changeset-bot Bot commented Aug 1, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: ff2e24c

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 2 packages
Name Type
evlog Patch
@evlog/cli Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Thank you for following the naming conventions! 🙏

@coderabbitai

coderabbitai Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Important

Review skipped

No new commits to review since the last review.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: e9af4304-8d4f-46f7-acf4-9104607d54b2

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The PR adds a shared asynchronous integration conformance suite. It validates event behavior, request IDs, route handling, exclusions, enrichment, draining, and response status across oRPC and Next.js integrations.

Changes

Integration conformance

Layer / File(s) Summary
Conformance contracts and harness
packages/evlog/src/shared/conformance.ts
Defines mount, request, check, and result contracts. Adds event collection, polling, route discovery, assertions, and cleanup helpers.
Behavioral checks and runner
packages/evlog/src/shared/conformance.ts
Adds checks for event fields, request-ID reuse, route service overrides, excluded routes, enrichment-before-drain ordering, and response status. Runs checks independently and normalizes failures.
Framework matrix adoption
packages/evlog/test/helpers/frameworkMatrix.ts, packages/evlog/test/frameworks/orpc.test.ts, packages/evlog/test/next/handler.test.ts, .changeset/integration-conformance-suite.md
Binds the shared checks to the framework matrix. Adds oRPC and Next.js HTTP coverage and documents the changes.
Estimated code review effort: 3 (Moderate) ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Vitest
  participant runIntegrationConformance
  participant ConformanceMount
  participant Integration
  Vitest->>runIntegrationConformance: run shared conformance checks
  runIntegrationConformance->>ConformanceMount: mount integration
  ConformanceMount->>Integration: send test requests
  Integration-->>runIntegrationConformance: return response status and events
  runIntegrationConformance-->>Vitest: return pass or failure result
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly identifies the test-focused change and names the oRPC and Next.js integrations covered by the shared conformance matrix.
Description check ✅ Passed The description explains the motivation, implementation, coverage, contract, documentation, and verification, but it omits the template checklist and explicit linked-issue section.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/integration-conformance-suite

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@pkg-pr-new

pkg-pr-new Bot commented Aug 1, 2026

Copy link
Copy Markdown
npm i https://pkg.pr.new/@evlog/cli@479
npm i https://pkg.pr.new/evlog@479
npm i https://pkg.pr.new/@evlog/nuxthub@479
npm i https://pkg.pr.new/@evlog/telemetry@479

commit: ff2e24c

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/docs/content/6.extend/10.custom-framework.md`:
- Around line 297-304: Declare or define the mount function before the Vitest
test uses it in check.run(mount), reusing the inline mount implementation from
the preceding example so the snippet works when copied in isolation. Keep the
existing integrationConformanceChecks test structure unchanged.

In `@packages/evlog/src/shared/conformance.ts`:
- Around line 16-21: Add per-field JSDoc comments to the exported public types
in conformance.ts: document each field of ConformanceRequest,
ConformanceCheck.name, and ConformanceResult, matching the existing
field-documentation style used by ConformanceApp and BaseEvlogOptions. Keep the
type shapes and behavior unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 284392ef-fdc1-4523-8124-1fd000ab8a82

📥 Commits

Reviewing files that changed from the base of the PR and between 1b97c2f and 5372053.

⛔ Files ignored due to path filters (1)
  • packages/evlog/test/toolkit/__snapshots__/api-surface.test.ts.snap is excluded by !**/*.snap
📒 Files selected for processing (7)
  • .changeset/integration-conformance-suite.md
  • apps/docs/content/6.extend/10.custom-framework.md
  • packages/evlog/src/shared/conformance.ts
  • packages/evlog/src/shared/index.ts
  • packages/evlog/test/frameworks/orpc.test.ts
  • packages/evlog/test/helpers/frameworkMatrix.ts
  • packages/evlog/test/next/handler.test.ts

Comment on lines +297 to +304
```typescript [test/conformance.test.ts]
import { it, expect } from 'vitest'
import { integrationConformanceChecks } from 'evlog/toolkit'

it.each(integrationConformanceChecks)('$name', async (check) => {
await expect(check.run(mount)).resolves.toBeUndefined()
})
```

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Undefined mount in the Vitest example.

This snippet references mount in check.run(mount), but the snippet never declares it. The preceding example passes an inline arrow function directly to runIntegrationConformance and never binds it to a mount variable, so a reader copying this snippet in isolation gets a ReferenceError.

📝 Proposed fix
 import { it, expect } from 'vitest'
 import { integrationConformanceChecks } from 'evlog/toolkit'
+import { mount } from './my-integration' // however your adapter exposes it

 it.each(integrationConformanceChecks)('$name', async (check) => {
   await expect(check.run(mount)).resolves.toBeUndefined()
 })
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/docs/content/6.extend/10.custom-framework.md` around lines 297 - 304,
Declare or define the mount function before the Vitest test uses it in
check.run(mount), reusing the inline mount implementation from the preceding
example so the snippet works when copied in isolation. Keep the existing
integrationConformanceChecks test structure unchanged.

Comment thread packages/evlog/src/shared/conformance.ts
@HugoRCD

HugoRCD commented Aug 1, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Consolidates the shared HTTP checks into `src/shared/conformance.ts` as
runner-agnostic functions that throw instead of calling `expect`, with
`describeStandardHttpMatrix` reduced to a Vitest binding over them — one
copy rather than two that can drift.

Adds two checks (an `exclude`d route is skipped but still served; `enrich`
runs before `drain` with the response status) and brings `evlog/orpc` and
`evlog/next` into the matrix. Both pass unmodified. The app may now declare
the `route` it serves rather than the suite assuming `/api/users`, which
surfaced a hardcoded `/api/**` in the per-route service check.

Deliberately **not** exported from `evlog/toolkit`. `mount()` injects
`drain` as a function, which only fits integrations configured per request.
`evlog/nitro`, `evlog/nitro/v3` and `evlog/nuxt` receive theirs through the
`evlog:drain` hook inside a built app, and a function cannot cross that
build boundary — so the suite structurally cannot drive evlog's flagship
integrations, and publishing it as "the contract every integration
satisfies" would be inaccurate. The failure mode is also still wrong: a
mount serving a 404 is reported as a conformance failure rather than a
broken mount.

Public API surface is unchanged.
@HugoRCD

HugoRCD commented Aug 1, 2026

Copy link
Copy Markdown
Owner Author

Thanks — both comments landed on `53720531`, before this PR was reworked. Status:

1. Undefined `mount` in the Vitest example (custom-framework.md:304) — obsolete. The whole "Verify your integration" docs section is gone: the suite is no longer exported from evlog/toolkit, so there is no public snippet to fix. See the rationale in the updated PR description.

2. Missing per-field JSDoc (conformance.ts:33) — valid on its merits, fixed. The stated reason no longer applies (the types are not exported publicly any more), but the inconsistency was real: ConformanceApp documented every field while ConformanceRequest, ConformanceCheck.name and ConformanceResult documented none. All three now carry per-field docs.

@HugoRCD
HugoRCD force-pushed the feat/integration-conformance-suite branch from 531bae2 to ff2e24c Compare August 1, 2026 17:38
@HugoRCD

HugoRCD commented Aug 1, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant