{"id":16201,"library":"rsc-test-helper","title":"RSC Test Helper","description":"rsc-test-helper is a utility designed to enable unit testing of React components that consume async/await React Server Components (RSCs) within client-side testing environments like `@testing-library/react` or `react-test-renderer`. As of version 0.1.4, this package provides a `patch` function that transforms an async React component tree into a synchronous one by awaiting promises, thus making them compatible with standard React test renderers which do not natively support async component types. This is particularly useful for projects utilizing Next.js App Directory beta features (introduced in Next.js 13 in October 2022 and stabilized in 13.4 in June 2023), where RSCs return promises, causing errors in testing setups. The package currently has an early-stage development status with an undefined release cadence, focusing on solving an immediate testing pain point before official React/Next.js testing support for RSCs. A key differentiator is its specific focus on resolving the \"Objects are not valid as a React child (found: [object Promise])\" error encountered when rendering async RSCs in tests, especially in environments like JSDOM.","status":"active","version":"0.1.4","language":"javascript","source_language":"en","source_url":"https://github.com/bizarre/rsc-test-helper","tags":["javascript","typescript"],"install":[{"cmd":"npm install rsc-test-helper","lang":"bash","label":"npm"},{"cmd":"yarn add rsc-test-helper","lang":"bash","label":"yarn"},{"cmd":"pnpm add rsc-test-helper","lang":"bash","label":"pnpm"}],"dependencies":[],"imports":[{"note":"The library is primarily distributed as an ESM module, requiring `import` syntax. Although TypeScript types are shipped, direct CommonJS `require` might lead to issues depending on the project's build configuration.","wrong":"const { patch } = require('rsc-test-helper');","symbol":"patch","correct":"import { patch } from 'rsc-test-helper';"}],"quickstart":{"code":"import React from \"react\";\nimport { render, screen } from \"@testing-library/react\";\nimport { patch } from \"rsc-test-helper\";\n\n// Mocking internal components for a self-contained, runnable example.\n// In a real application, these would be imported from their respective files.\nconst RoomChatParticipants = async () => {\n  // Simulate an async operation, like data fetching in a Server Component\n  await new Promise(resolve => setTimeout(resolve, 100)); \n  return <div data-testid=\"chat-participants\">Participants List (from RSC)</div>;\n};\n\nconst RoomChatBox = ({ subheading }: { subheading: string }) => (\n  <div data-testid=\"chat-box\">Chat Box: {subheading}</div>\n);\n\nconst Skeleton = () => <div data-testid=\"skeleton\">Loading participants...</div>;\n\n// This component uses an async RSC (RoomChatParticipants)\nconst RoomPage = () => {\n  return (\n    <div>\n      <section>\n        <RoomChatBox subheading={\"Welcome\"} />\n        <React.Suspense fallback={<Skeleton />}>\n          {/* @ts-expect-error Server Component: This is a known Next.js/React pattern when using async RSCs directly in JSX */}\n          <RoomChatParticipants />\n        </React.Suspense>\n      </section>\n    </div>\n  );\n};\n\ndescribe(\"Room Page with Async RSCs\", () => {\n  it(\"renders chat box and participants after patching async components\", async () => {\n    // Without 'patch', render(<RoomPage />) would throw an error\n    // 'Objects are not valid as a React child (found: [object Promise])'.\n\n    // 'patch' transforms the async component tree to be synchronously renderable.\n    const ComponentToRender = await patch(<RoomPage />);\n    render(<ComponentToRender />);\n\n    // Verify synchronous client components are rendered\n    const chatBox = screen.getByTestId(\"chat-box\");\n    expect(chatBox).toBeInTheDocument();\n    expect(chatBox).toHaveTextContent(\"Welcome\");\n\n    // Verify the async RSC content is rendered after patching\n    const participants = screen.getByTestId(\"chat-participants\");\n    expect(participants).toBeInTheDocument();\n    expect(participants).toHaveTextContent(\"Participants List (from RSC)\");\n\n    // The skeleton fallback for Suspense is bypassed by 'patch' because promises are awaited.\n    expect(screen.queryByTestId(\"skeleton\")).not.toBeInTheDocument();\n  });\n});","lang":"typescript","description":"This quickstart demonstrates how to use `rsc-test-helper`'s `patch` function to enable unit testing of a React component tree that includes an asynchronous React Server Component (RSC) within a standard testing environment like `@testing-library/react`. It shows how to resolve the common 'Objects are not valid as a React child' error by awaiting and transforming the component before rendering."},"warnings":[{"fix":"For testing fallback states, alternative strategies (e.g., mocking the async component to return a pending promise, or using a different testing approach that doesn't resolve promises) would be necessary, but are outside the scope of this helper.","message":"The `patch` function, by its nature of awaiting all promises, prevents the direct testing of `<Suspense>` fallback states for the patched async components. It resolves the full component tree, bypassing intermediate loading states.","severity":"gotcha","affected_versions":">=0.1.0"},{"fix":"Users should exercise caution and thoroughly test their applications when updating, and ideally, pin to exact versions or ranges only after careful consideration in production environments.","message":"This package is explicitly described as an 'early-stage development' and 'super dirty helper' (v0.1.4), indicating potential instability, unhandled edge cases, and that future updates, especially leading to a 1.0 release, may introduce breaking changes or significant refactors.","severity":"gotcha","affected_versions":">=0.1.0"},{"fix":"Components containing server-side logic might need to be mocked or abstracted for unit tests using this helper, or a Node.js-based test environment might be required for true integration testing of server-side code.","message":"The helper processes React elements in a client-side (e.g., JSDOM) testing environment. Server-side-only code, such as direct database access or other Node.js-specific APIs used within actual React Server Components, will not function correctly and may throw errors. The helper focuses on the React element transformation, not full server environment simulation.","severity":"gotcha","affected_versions":">=0.1.0"}],"env_vars":null,"last_verified":"2026-04-21T00:00:00.000Z","next_check":"2026-07-20T00:00:00.000Z","problems":[{"fix":"Apply the `patch` function from `rsc-test-helper` to your root component before rendering. For example: `const Component = await patch(<YourRootComponent />); render(<Component />);`. This transforms the async component tree into a synchronous one by resolving all promises.","cause":"React test renderers (e.g., `@testing-library/react` or `react-test-renderer`) do not natively expect async function components (like React Server Components) to return a Promise directly. When an async component is included in JSX, its return value is a Promise, which React's reconciliation process cannot render as a valid child.","error":"Objects are not valid as a React child (found: [object Promise]). If you meant to render a collection of children, use an array instead."}],"ecosystem":"npm"}