Skip to content

Conversation

@Mathiasduc
Copy link

@Mathiasduc Mathiasduc commented Oct 31, 2025

Summary by CodeRabbit

  • Chores

    • Added compression support dependencies to development environment.
  • Tests

    • Added comprehensive NestJS integration tests covering response types, middleware, guards, interceptors, error handling, and compression across multiple server adapters.

@vercel
Copy link

vercel bot commented Oct 31, 2025

@Mathiasduc is attempting to deploy a commit to the unnoq-team Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai
Copy link

coderabbitai bot commented Oct 31, 2025

Walkthrough

This PR adds three compression-related devDependencies to the Nest package and introduces two comprehensive integration test suites for NestJS—one covering core Nest features (interceptors, guards, pipes, middleware, compression) and another validating all supported oRPC response types across different adapters.

Changes

Cohort / File(s) Summary
Compression Dependencies
packages/nest/package.json
Added three devDependencies: @fastify/compress, @types/compression, and compression for compression support.
Nest Features Test Suite
packages/nest/tests/nest-features.test.ts
New comprehensive integration test file covering oRPC features with multiple controllers, interceptors, guards, pipes, middleware, filters, and modules. Tests raw/detailed output, response transformation, global pipes, role-based guards, exception handling, global interceptors, and compression integration across Express and Fastify adapters.
Response Types Test Suite
packages/nest/tests/response-types.test.ts
New integration test file validating all supported ORPC response types (empty, string, object, array, URLSearchParams, FormData, Blob, File, SSE with/without metadata, detailed responses). Tests response serialization, content-types, SSE parsing, event metadata, and resumption via Last-Event-ID across adapters.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50-70 minutes

  • test file structure & contract definitions: Verify correctness of oRPC contracts and response type expectations across all test cases
  • adapter compatibility: Ensure tests accurately cover behavior differences between Express and Fastify adapters, particularly compression handling
  • middleware & guard chains: Review order of execution and interaction patterns for interceptors, guards, pipes, and filters
  • SSE and streaming logic: Validate event parsing, metadata handling, and Last-Event-ID resumption semantics
  • compression integration: Confirm compression middleware registration and response handling align with oRPC expectations

Possibly related PRs

Suggested labels

size:XL

Poem

🐰 A hop through compression and tests so vast,
Express and Fastify adapters unsurpassed,
Response types dancing, from Blob to SSE,
Guards and interceptors—what a spree!
NestJS features fully blessed,
Our fuzzy friend puts code to the test! 🧪✨

Pre-merge checks and finishing touches

✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The pull request title 'chore(nest): add more test for Nest features compatibilty' directly reflects the main changes in the changeset. The PR adds three new test files (nest-features.test.ts, response-types.test.ts) and supporting dependencies for testing NestJS features compatibility. The title accurately captures the primary purpose of adding comprehensive tests for Nest framework integration, though it contains a typo ('compatibilty' should be 'compatibility').
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 05476c2 and ec54944.

📒 Files selected for processing (2)
  • packages/nest/tests/nest-features.test.ts (1 hunks)
  • packages/nest/tests/response-types.test.ts (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
packages/nest/tests/nest-features.test.ts (2)
packages/contract/src/builder.ts (1)
  • oc (189-198)
packages/nest/src/implement.ts (1)
  • Injectable (102-165)
packages/nest/tests/response-types.test.ts (2)
packages/contract/src/builder.ts (1)
  • oc (189-198)
packages/nest/tests/nest-features.test.ts (1)
  • data (252-261)

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 and usage tips.

Copy link
Owner

Choose a reason for hiding this comment

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

Because there tests do not have corresponding .ts file so you should put them into tests folder instead of src

@pkg-pr-new
Copy link

pkg-pr-new bot commented Oct 31, 2025

More templates

@orpc/ai-sdk

npm i https://pkg.pr.new/@orpc/ai-sdk@1156

@orpc/arktype

npm i https://pkg.pr.new/@orpc/arktype@1156

@orpc/client

npm i https://pkg.pr.new/@orpc/client@1156

@orpc/contract

npm i https://pkg.pr.new/@orpc/contract@1156

@orpc/experimental-durable-iterator

npm i https://pkg.pr.new/@orpc/experimental-durable-iterator@1156

@orpc/hey-api

npm i https://pkg.pr.new/@orpc/hey-api@1156

@orpc/interop

npm i https://pkg.pr.new/@orpc/interop@1156

@orpc/json-schema

npm i https://pkg.pr.new/@orpc/json-schema@1156

@orpc/nest

npm i https://pkg.pr.new/@orpc/nest@1156

@orpc/openapi

npm i https://pkg.pr.new/@orpc/openapi@1156

@orpc/openapi-client

npm i https://pkg.pr.new/@orpc/openapi-client@1156

@orpc/otel

npm i https://pkg.pr.new/@orpc/otel@1156

@orpc/experimental-publisher

npm i https://pkg.pr.new/@orpc/experimental-publisher@1156

@orpc/react

npm i https://pkg.pr.new/@orpc/react@1156

@orpc/react-query

npm i https://pkg.pr.new/@orpc/react-query@1156

@orpc/experimental-react-swr

npm i https://pkg.pr.new/@orpc/experimental-react-swr@1156

@orpc/server

npm i https://pkg.pr.new/@orpc/server@1156

@orpc/shared

npm i https://pkg.pr.new/@orpc/shared@1156

@orpc/solid-query

npm i https://pkg.pr.new/@orpc/solid-query@1156

@orpc/standard-server

npm i https://pkg.pr.new/@orpc/standard-server@1156

@orpc/standard-server-aws-lambda

npm i https://pkg.pr.new/@orpc/standard-server-aws-lambda@1156

@orpc/standard-server-fastify

npm i https://pkg.pr.new/@orpc/standard-server-fastify@1156

@orpc/standard-server-fetch

npm i https://pkg.pr.new/@orpc/standard-server-fetch@1156

@orpc/standard-server-node

npm i https://pkg.pr.new/@orpc/standard-server-node@1156

@orpc/standard-server-peer

npm i https://pkg.pr.new/@orpc/standard-server-peer@1156

@orpc/svelte-query

npm i https://pkg.pr.new/@orpc/svelte-query@1156

@orpc/tanstack-query

npm i https://pkg.pr.new/@orpc/tanstack-query@1156

@orpc/trpc

npm i https://pkg.pr.new/@orpc/trpc@1156

@orpc/valibot

npm i https://pkg.pr.new/@orpc/valibot@1156

@orpc/vue-colada

npm i https://pkg.pr.new/@orpc/vue-colada@1156

@orpc/vue-query

npm i https://pkg.pr.new/@orpc/vue-query@1156

@orpc/zod

npm i https://pkg.pr.new/@orpc/zod@1156

commit: ec54944

@Mathiasduc Mathiasduc marked this pull request as ready for review November 3, 2025 08:26
@dosubot dosubot bot added the size:XXL This PR changes 1000+ lines, ignoring generated files. label Nov 3, 2025
@Mathiasduc Mathiasduc force-pushed the chore/nest/add-test-for-nest-features branch from f072381 to 05476c2 Compare November 3, 2025 08:28
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5c38c37 and 05476c2.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (3)
  • packages/nest/package.json (1 hunks)
  • packages/nest/src/test/nest-features.test.ts (1 hunks)
  • packages/nest/src/test/response-types.test.ts (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
packages/nest/src/test/response-types.test.ts (2)
packages/contract/src/builder.ts (1)
  • oc (189-198)
packages/nest/src/test/nest-features.test.ts (1)
  • data (252-261)
packages/nest/src/test/nest-features.test.ts (2)
packages/contract/src/builder.ts (1)
  • oc (189-198)
packages/nest/src/implement.ts (1)
  • Injectable (102-165)
🔇 Additional comments (1)
packages/nest/package.json (1)

64-75: Compression tooling addition makes sense

These devDependencies line up with the new compression middleware scenarios in the Nest integration tests, so no objections from my side.

Comment on lines +545 to +575
it('should work with global exception filters (useGlobalFilters)', async () => {
await createApp(TestErrorModule, {})

// Request that doesn't throw should succeed
await request(app.getHttpServer())
.post('/error')
.send({ shouldThrow: false })
.expect(200)
.then((response) => {
expect(response.body).toEqual({ message: 'No error' })
})

// Errors thrown inside oRPC handlers are now allowed to bubble up to NestJS
// so global exception filters can catch and transform them
await request(app.getHttpServer())
.post('/error')
.send({ shouldThrow: true })
.expect(418) // Custom status code from the HttpException
.then((response) => {
// The response should be transformed by GlobalHttpExceptionFilter
expect(response.body).toMatchObject({
statusCode: 418,
message: 'Custom error from handler',
customFilter: true, // Marker to verify the filter ran
})
expect(response.body.timestamp).toBeDefined()
})

// Ensure that the standard response was not sent via ORPCExceptionFilter
expect(sendStandardResponseSpy).not.toHaveBeenCalled()
})
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Clear the spy before asserting the error path

In this test we first hit /error with shouldThrow: false, which inevitably calls StandardServerNode.sendStandardResponse. Without clearing the spy afterwards, the later expect(sendStandardResponseSpy).not.toHaveBeenCalled() can never pass. It also accumulates calls across previous Express tests. Please reset the spy before exercising the error scenario (and ideally in a beforeEach) so the assertion actually validates that the exceptional flow bypasses the standard responder.

-        await request(app.getHttpServer())
+        await request(app.getHttpServer())
           .post('/error')
           .send({ shouldThrow: false })
           .expect(200)
           .then((response) => {
             expect(response.body).toEqual({ message: 'No error' })
           })
 
+        sendStandardResponseSpy.mockClear()
+
         // Errors thrown inside oRPC handlers are now allowed to bubble up to NestJS
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
it('should work with global exception filters (useGlobalFilters)', async () => {
await createApp(TestErrorModule, {})
// Request that doesn't throw should succeed
await request(app.getHttpServer())
.post('/error')
.send({ shouldThrow: false })
.expect(200)
.then((response) => {
expect(response.body).toEqual({ message: 'No error' })
})
// Errors thrown inside oRPC handlers are now allowed to bubble up to NestJS
// so global exception filters can catch and transform them
await request(app.getHttpServer())
.post('/error')
.send({ shouldThrow: true })
.expect(418) // Custom status code from the HttpException
.then((response) => {
// The response should be transformed by GlobalHttpExceptionFilter
expect(response.body).toMatchObject({
statusCode: 418,
message: 'Custom error from handler',
customFilter: true, // Marker to verify the filter ran
})
expect(response.body.timestamp).toBeDefined()
})
// Ensure that the standard response was not sent via ORPCExceptionFilter
expect(sendStandardResponseSpy).not.toHaveBeenCalled()
})
it('should work with global exception filters (useGlobalFilters)', async () => {
await createApp(TestErrorModule, {})
// Request that doesn't throw should succeed
await request(app.getHttpServer())
.post('/error')
.send({ shouldThrow: false })
.expect(200)
.then((response) => {
expect(response.body).toEqual({ message: 'No error' })
})
sendStandardResponseSpy.mockClear()
// Errors thrown inside oRPC handlers are now allowed to bubble up to NestJS
// so global exception filters can catch and transform them
await request(app.getHttpServer())
.post('/error')
.send({ shouldThrow: true })
.expect(418) // Custom status code from the HttpException
.then((response) => {
// The response should be transformed by GlobalHttpExceptionFilter
expect(response.body).toMatchObject({
statusCode: 418,
message: 'Custom error from handler',
customFilter: true, // Marker to verify the filter ran
})
expect(response.body.timestamp).toBeDefined()
})
// Ensure that the standard response was not sent via ORPCExceptionFilter
expect(sendStandardResponseSpy).not.toHaveBeenCalled()
})
🤖 Prompt for AI Agents
In packages/nest/src/test/nest-features.test.ts around lines 545 to 575, the
test leaves sendStandardResponseSpy populated from the non-error request,
causing the final expectation to always fail; clear or reset the spy before
exercising the error scenario (or better, in a beforeEach for the suite) so that
the later expect(sendStandardResponseSpy).not.toHaveBeenCalled() actually
verifies the error path—use sendStandardResponseSpy.mockClear() / mockReset()
(or jest.clearAllMocks()) immediately after the non-throwing request (or in
beforeEach) so the spy has zero calls before the failing request.

Comment on lines +441 to +458
if (!response.text) {
// Skip if response is undefined (GET with body may not be supported in all scenarios)
return
}

// Parse SSE format
const events = response.text
.split('\n\n')
.filter(Boolean)
.map((event) => {
const dataMatch = event.match(/data: (.+)/)
return dataMatch ? JSON.parse(dataMatch[1] as string) : null
})
.filter(Boolean)

// Verify we got all events
expect(events.length).toBeGreaterThanOrEqual(3)
expect(events[0]).toMatchObject({ message: 'Event 1', index: 0 })
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Don’t skip SSE assertions on missing payload

Line 441 currently bails out whenever response.text is falsy, which means the test silently passes even if the stream never delivered any events. That defeats the purpose of the coverage. Please assert that the payload exists before parsing (and apply the same fix to the other SSE helpers below) so a broken stream actually fails the test.

-          if (!response.text) {
-            // Skip if response is undefined (GET with body may not be supported in all scenarios)
-            return
-          }
-
-          // Parse SSE format
-          const events = response.text
+          const rawStream = response.text
+          expect(rawStream, 'SSE payload should not be empty').toBeTruthy()
+
+          // Parse SSE format
+          const events = rawStream
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (!response.text) {
// Skip if response is undefined (GET with body may not be supported in all scenarios)
return
}
// Parse SSE format
const events = response.text
.split('\n\n')
.filter(Boolean)
.map((event) => {
const dataMatch = event.match(/data: (.+)/)
return dataMatch ? JSON.parse(dataMatch[1] as string) : null
})
.filter(Boolean)
// Verify we got all events
expect(events.length).toBeGreaterThanOrEqual(3)
expect(events[0]).toMatchObject({ message: 'Event 1', index: 0 })
const rawStream = response.text
expect(rawStream, 'SSE payload should not be empty').toBeTruthy()
// Parse SSE format
const events = rawStream
.split('\n\n')
.filter(Boolean)
.map((event) => {
const dataMatch = event.match(/data: (.+)/)
return dataMatch ? JSON.parse(dataMatch[1] as string) : null
})
.filter(Boolean)
// Verify we got all events
expect(events.length).toBeGreaterThanOrEqual(3)
expect(events[0]).toMatchObject({ message: 'Event 1', index: 0 })
🤖 Prompt for AI Agents
In packages/nest/src/test/response-types.test.ts around lines 441 to 458, the
test currently returns early when response.text is falsy which masks missing SSE
payloads; replace the early return with an explicit assertion that response.text
is defined/non-empty (e.g. expect(response.text).toBeTruthy() or
toHaveLength(...) ) so the test fails when no SSE payload is present, then
proceed to parse the SSE text and run the existing event-count and content
assertions; apply the same change to the other SSE helper/test blocks mentioned
in the comment.

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

Labels

size:XXL This PR changes 1000+ lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants