在渲染所有组件后,如何从表中获取元素?

发布于 2025-02-05 17:51:00 字数 2520 浏览 4 评论 0原文

我正在尝试测试我在React中的Userstable页面,但是测试库在有时间渲染之前获得了元素。 请在下面查看我的代码:

userstable.js

import React, { useState, useEffect } from 'react';
import { Link } from 'react-router-dom';
import Table from 'react-bootstrap/Table';
import { fetchUsers } from 'api';


function UsersTable() {
    const [users, setUsers] = useState([]);

    useEffect(() => {
        const getUsers = async () => {
            const data = await fetchUsers();
            setUsers(data);
        };

        getUsers();
    }, []);


    const renderUsers = () => users.map((user) => {
        const { id, fullName, email } = user;

        return (
            <tr key={ id } >
                <td>
                    <Link to={ `user/${id}` }>{ fullName }</Link>
                </td>
                <td>
                    <Link to={ `user/${id}/mail` }>{ email }</Link>
                </td>
            </tr>
        );
    });
    return (
        <div data-testid='userTest' className="users-table">
            <h1>Users</h1>
            <Table striped borderless>
                <thead>
                    <tr style={{
                            borderBottom: "1px solid #cccccc"
                        }}> 
                        <th>User</th>
                        <th>Email</th>
                    </tr>
                </thead>
                <tbody>
                    { renderUsers() }
                </tbody>
            </Table>
        </div>
    );
}

export default UsersTable;

usertable.test.js

import { render } from '@testing-library/react'
import React from 'react';
import { BrowserRouter as Router } from 'react-router-dom';
import '@testing-library/jest-dom/extend-expect';
import UserTable from '../components/users/UserTable';




test("Test #1: Count Users", async () => {

    const component = render(
        <Router>
            <UserTable />
        </Router>
    );

    const users = component.getByTestId('userTest')
    expect(users.querySelectorAll('tr').length).toBe(193)
})

note &lt; router&gt;预防错误错误:未介绍[错误:不变失败:您不应使用&lt; link&gt;外部A&lt; router&gt;

期望:期望有192个用户 + 1行包含thead ,但是我仅获得1行包含thead

I'm trying to test my UsersTable page in React, but the testing library gets the elements before they have time to render.
Please check my code below:

UsersTable.js

import React, { useState, useEffect } from 'react';
import { Link } from 'react-router-dom';
import Table from 'react-bootstrap/Table';
import { fetchUsers } from 'api';


function UsersTable() {
    const [users, setUsers] = useState([]);

    useEffect(() => {
        const getUsers = async () => {
            const data = await fetchUsers();
            setUsers(data);
        };

        getUsers();
    }, []);


    const renderUsers = () => users.map((user) => {
        const { id, fullName, email } = user;

        return (
            <tr key={ id } >
                <td>
                    <Link to={ `user/${id}` }>{ fullName }</Link>
                </td>
                <td>
                    <Link to={ `user/${id}/mail` }>{ email }</Link>
                </td>
            </tr>
        );
    });
    return (
        <div data-testid='userTest' className="users-table">
            <h1>Users</h1>
            <Table striped borderless>
                <thead>
                    <tr style={{
                            borderBottom: "1px solid #cccccc"
                        }}> 
                        <th>User</th>
                        <th>Email</th>
                    </tr>
                </thead>
                <tbody>
                    { renderUsers() }
                </tbody>
            </Table>
        </div>
    );
}

export default UsersTable;

userTable.test.js

import { render } from '@testing-library/react'
import React from 'react';
import { BrowserRouter as Router } from 'react-router-dom';
import '@testing-library/jest-dom/extend-expect';
import UserTable from '../components/users/UserTable';




test("Test #1: Count Users", async () => {

    const component = render(
        <Router>
            <UserTable />
        </Router>
    );

    const users = component.getByTestId('userTest')
    expect(users.querySelectorAll('tr').length).toBe(193)
})

Note: <Router> prevents the error Error: Uncaught [Error: Invariant failed: You should not use <Link> outside a <Router>

Expect: Expecting to have 192 users + 1 row containing thead, but instead I get 1 row containing only the thead.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

清秋悲枫 2025-02-12 17:51:00
expect(getByTestId('userTest').children.length).toBe(193);
expect(getByTestId('userTest').children.length).toBe(193);
撩起发的微风 2025-02-12 17:51:00

问题在于您的测试正在尝试访问useffect hook userstable 已完成获取和渲染数据之前。

您可以使用reacts @testing-library's findbywaitfor方法等待组件异步渲染组件数据。

import { render, screen, waitFor } from '@testing-library/react';
import React from 'react';
import { BrowserRouter as Router } from 'react-router-dom';
import '@testing-library/jest-dom/extend-expect';
import UsersTable from '../components/users/UserTable';


jest.mock('api', () => ({ // Mocking fetch user API call
    fetchUsers: jest.fn(() =>
        Promise.resolve(
            Array.from({ length: 192 }, (_, i) => ({
                id: i + 1,
                fullName: `User ${i + 1}`,
                email: `user${i + 1}@example.com`,
            }))
        )
    ),
}));

test('Test #1: Count Users', async () => {
    render(
        <Router>
            <UsersTable />
        </Router>
    );

    // Waiting for the rows to rendered including the header row
    await waitFor(() => { 
        expect(screen.getAllByRole('row').length).toBe(193);
    });
});

这将保证在数据可用之前避免异步渲染并避免查询。

The issue Is that your test is trying to access the DOM elements before the useEffect hook in UsersTable has completed fetching and rendering the data.

You can use reacts @testing-library's findBy or waitFor methods to wait for the components to render your component data asynchronously.

import { render, screen, waitFor } from '@testing-library/react';
import React from 'react';
import { BrowserRouter as Router } from 'react-router-dom';
import '@testing-library/jest-dom/extend-expect';
import UsersTable from '../components/users/UserTable';


jest.mock('api', () => ({ // Mocking fetch user API call
    fetchUsers: jest.fn(() =>
        Promise.resolve(
            Array.from({ length: 192 }, (_, i) => ({
                id: i + 1,
                fullName: `User ${i + 1}`,
                email: `user${i + 1}@example.com`,
            }))
        )
    ),
}));

test('Test #1: Count Users', async () => {
    render(
        <Router>
            <UsersTable />
        </Router>
    );

    // Waiting for the rows to rendered including the header row
    await waitFor(() => { 
        expect(screen.getAllByRole('row').length).toBe(193);
    });
});

This will guarantee asynchronous rendering and avoid querying before the data is available.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文