1

我正在尝试使用 React 测试库对一个简单的导航应用程序进行简单的测试。我目前正在尝试使用RTL's own guide中显示的示例方法,但这似乎不起作用。

应用程序.js

return (
    <BrowserRouter>
      <div>
        <Route exact path="/" component={Home} />
        <Route exact path="/hello" component={Hello} />
      </div>
    </BrowserRouter>
  );

主页.jsx

return (
    <div data-testid="home-container">
      <Link to="/hello">Link to hello</Link>
    </div>
  );

你好.jsx

return (
    <div data-testid="hello-container">
      <Link to="/">&lt; Back</Link>
      <h1 data-testid="hello-title">Hello component</h1>
    </div>
  );

在 Home.spec.js 中测试 Home.jsx

test("Navigate to hello page when clicked", async () => {
    const history = createMemoryHistory();
    render(
      <Router history={history}>
        <Home />
      </Router>
    );

    // check pre-nav page
    expect(screen.getByText(/Link to hello/i)).toBeInTheDocument();

    const leftClick = { button: 0 };
    userEvent.click(screen.getByText(/Link to hello/i), leftClick);

    // check we have navigated to the correct path - THIS PASSES!
    expect(history.location.pathname).toBe("/hello");

    // check that the content changed to the new page - THIS FAILS!
    expect(screen.getByText(/Hello component/i)).toBeInTheDocument();
  });

错误...

我似乎得到的错误是它找不到/Hello component/文本,仍然认为它在Home组件上......这很奇怪,因为历史位置检查清楚地表明它在Hello路径上。

Unable to find an element with the text: /Hello component/i. This could be because the text is broken up by multiple elements. In this case, you can provide a function for your text matcher to make your matcher more flexible.

Ignored nodes: comments, <script />, <style />
<body>
  <div>
    <div
      data-testid="home-container"
    >
      <a
        href="/hello"
      >
        Link to hello
      </a>
    </div>
  </div>
</body>
4

2 回答 2

1
    render(
      <Router history={history}>
        <App /> // <<--
      </Router>
    );

你想使用你的App组件,因为它有路由,你的Home组件不知道路由。

于 2021-06-26T23:02:56.727 回答
0

感谢@BrunoNoriller 帮助我在这里看到我的方式的错误。

我最初的问题的主要问题是让我自己对我认为我正在接受测试的内容感到困惑。

我以为我正在对组件执行单元测试,只是测试从组件进行的路由以显示<Hello/>组件。事实上,我真正做的是对更广泛的应用程序及其路由进行伪 E2E 测试,其中 - 是的 - Bruno 的回答是正确的,渲染<App />组件并使用窗口历史记录让测试知道我们在哪里/我们去哪里。

我真正想要的是对孤立的组件,我只是忘记了这样做的范围。handleClick主要的类比是当您单击该组件中的按钮时,您的组件会采用某种功能来触发。在测试方面,您并不真正关心可触发的功能是什么,只需要我们传入一个并测试它是否会触发。这类似于组件内的隔离测试路由...假设您有一个<Link>,单击时会像我的组件一样路由到/hello;我们实际上并不关心在此结束时渲染的组件或页面(就像您在 E2E 测试中所做的那样),我们只关心渲染的内容,我们可以在测试中控制它。

主页.jsx

return (
    <div data-testid="home-continer">
        <Link to="/hello">Link to hello</Link>
    </div>
);

你好.jsx

return (
    <div data-testid="hello-continer">
        <Link to="/">Back</Link>
        <div>This is the real hello component</div>
    </div>
);

主页.spec.js

test('should render whatever is at /hello path when clicked', () => {
    /* 
      Essentially we are rendering a new, custom router for the 
      test to route to a test-specific version of the route we 
      render in the component under test
    */
    render(
      <BrowserRouter>
        <Home />
        <Route path="/hello">
          <div data-testid="hello-container">
             TEST HELLO
          </div>
        </Route>
      </BrowserRouter>
    );

    // Test we're at the correct starting point in the <Home> component
    expect(rendered.getByText(/Link to hello/i)).toBeInTheDocument();

    // Click the link to the /hello path
    fireEvent.click(rendered.getByText(/Link to hello/i));

    // Test we can now see the path-specific component contents
    expect(rendered.getByTestId("hello-container")).toBeTruthy();

    /* 
      This test shows that we are showing the test-specific path 
      contents, not the real <App/> path route component contents
    */
    expect(rendered.getByTestId("hello-container").textContent)
        .toContain("TEST HELLO");

});
于 2021-06-27T16:42:14.693 回答