测试嵌套服务器组件

问题描述 投票:0回答:3

我已经通过使用异步

it
成功测试了一个隔离的服务器组件,并等待组件调用的输出作为普通函数传递到渲染中:

  it('renders the user data when user is authenticated', async () => {

    render(await UserData())

    expect(screen.getByTestId('user-data')).toBeInTheDocument();
  });

^ 有效并通过。

但我还有一个 page.tsx 服务器组件,它呈现另一个服务器组件 -

<UserData />
- 嵌套在其中:

'use server'

import styles from './page.module.css';
import LogInOut from "./LogInOut/LogInOut";
import UserData from "./UserData";

export default async function Page() {
  return (
    <main className={styles.main}>
      <h1>Title</h1>
      <LogInOut/>
      <UserData />
    </main>
  );
}

// Note: LogInOut is a client component, removing it doesn't help the problem.

...如果我尝试相同的技术来测试这个组件,即:

  it('renders a heading', async () => {

    render(await Page());

    const heading = screen.getByRole('heading', { level: 1 });

    expect(heading).toBeInTheDocument();
  });

^ ...这不起作用——我收到一条错误消息:

错误:未捕获[错误:对象作为 React 子对象无效(发现: [对象承诺])。如果你想渲染一组孩子, 请改用数组。]

我们如何测试嵌套的服务器组件? 我想要一种解决方案,允许我在单元测试中渲染父服务器组件和后代服务器组件,而无需模拟其中一个或另一个。

reactjs jestjs react-testing-library react-server-components next.js14
3个回答
1
投票

似乎对 react-testing-library 的支持不多,请参见这里。使用

Suspense
怎么样,你尝试过吗?

import { render, screen } from "@testing-library/react";
import { Suspense } from "react";

it('renders a heading', async () => {
  render(
    <Suspense>
      <Page />
    </Suspense>
  );

  const heading = await screen.getByRole('heading', { level: 1 });

  expect(heading).toBeInTheDocument();
});

0
投票

React 测试库的Issue 1209的讨论仍在进行中:

  • 对于嵌套的异步组件,你确实会面临尝试渲染 Promise 的错误,因为当前的解决方法是在客户端渲染服务器组件,而客户端不支持异步组件。
    这个自定义渲染函数 破解 React 内部结构以在测试中渲染服务器组件。 它的工作原理是 一个接一个地获取异步子级,并手动预渲染它们。

  • 对于更简单的情况(无嵌套),您应该简单地使用

    Suspense


-1
投票

您遇到的错误是因为您尝试使用await异步渲染React组件,但渲染函数需要同步组件。

试试这个方法:

it('renders a heading', async () => {
  const page = await Page(); // Resolve the promise before rendering
  render(page);

  const heading = screen.getByRole('heading', { level: 1 });

  expect(heading).toBeInTheDocument();
});
© www.soinside.com 2019 - 2024. All rights reserved.