使用react-testing-library测试material-ui datagrid时出现问题

22

我希望测试我的material-ui datagrid的内容,但测试结果只显示前3列(共8列)。我可以测试这3列的内容,没有问题。
在web浏览器上,一切都正常渲染。

我猜测这是由于datagrid的宽度和高度引起的,因为有这些警告,但我在文档中找不到解决方案。

Material-UI: useResizeContainer - The parent of the grid has an empty width.
You need to make sure the container has an intrinsic width.
The grid displays with a width of 0px.

You can find a solution in the docs:
https://material-ui.com/components/data-grid/rendering/#layout

Material-UI: useResizeContainer - The parent of the grid has an empty height.
You need to make sure the container has an intrinsic height.
The grid displays with a height of 0px.

You can find a solution in the docs:
https://material-ui.com/components/data-grid/rendering/#layout

这也可能是由于 mount 函数造成的: (根据 material-ui 文档,你应该使用 enzyme 的 mount 函数作为 createMount 函数的参数,但我正在使用 react 17,官方的 enzyme 适配器还没有发布。我尝试了 @wojtekmaj/enzyme-adapter-react-17 ,但没有改变任何东西。我目前正在使用 @testing-library/react 的 'render' 函数)

const mount = createMount({mount:render})

这是我组件的简化版本:

import React from "react";
import { DataGrid } from '@material-ui/data-grid';
import Button from "@material-ui/core/Button";


const Gridtest = (props) => {

const columns = [
    {field: 'id', headerName: 'ID', type: 'number',headerAlign: 'left', width: 130 },
    {field: 'tenant_id', headerName: 'Tenant ID', type: 'number',headerAlign: 'left', width: 130 },
    {field: 'user_reference', headerName: 'Customer user reference', type: 'string',headerAlign: 'left', width: 250 },
    {field: 'provider_name', headerName: 'Provider name', type: 'string',headerAlign: 'left', width: 220 },
    {field: 'provider_id', headerName: 'Provider ID', type: 'number',headerAlign: 'left', width: 130 },
    {field: 'expiration_date', headerName: 'Expiration date', type: 'dateTime',headerAlign: 'left', width: 220 },
    {field: 'last_start', headerName: 'Last start date', type: 'dateTime',headerAlign: 'left', width: 130 },
    {field: 'Action',
        headerName: 'Action',
        headerAlign: 'left',
        width: 100,
        renderCell: (params) => {
            return (
                <div>
                    <Button variant="contained" size="small" color="primary" disableRipple
                            onClick={() => null}>
                        Details
                    </Button>
                </div>
            )
        },
    },
];

const rows = [
    {
        "id": "10190",
        "tenant_id": "12201",
        "user_reference": "Xuser_ref",
        "provider_name": "Xprovider",
        "provider_id": "122",
        "expiration_date": "2020-04-07T17:36:40+02:00",
        "last_start": "2020-07-06T17:36:40+02:00"

    },
    {
        "id": "23541",
        "tenant_id": "96542",
        "user_reference": "Yuser_ref",
        "provider_name": "Yprovider",
        "provider_id": "856",
        "expiration_date": "2010-07-07T17:36:40+02:00",
        "last_start": "2010-09-06T17:36:40+02:00"

    }]

return(
    <main>
        <div style={{ display: 'flex', height: '100%',width: '100%', flexGrow: 1 }}>
            <DataGrid style={{height: '100%', width: '100%'}} autoHeight rows={rows} columns={columns} pageSize={5} checkboxSelection={false} hideFooterSelectedRowCount/>
        </div>
    </main>
)};

export default Gridtest;

我更简单组件的测试文件(测试成功):

import {screen, render, act, findByTestId} from '@testing-library/react'
import React from 'react'
import '@testing-library/jest-dom/extend-expect'
import Gridtest from '../../src/Gridtest'
import { createMount } from '@material-ui/core/test-utils';

describe('grid test', () => {

    const mount = createMount({mount:render})

    test('grid render', async () => {
        await act(async () => {
            mount(
                <Gridtest />
            );
        });
        expect(await screen.findByRole('grid')).toBeInTheDocument()
        expect(await screen.findAllByRole('columnheader')).toHaveLength(3)
        screen.debug(await screen.findByRole('grid'))
    })
})

screen.debug(await screen.findByRole('grid')) 返回:

<div
  aria-colcount="8"
  aria-label="grid"
  aria-multiselectable="false"
  aria-rowcount="2"
  class="MuiDataGrid-root MuiDataGrid-root"
  role="grid"
  style="width: 0px; height: 175px;"
  tabindex="0"
>
  <div />
  <div
    class="MuiDataGrid-mainGridContainer"
  >
    <div
      class="MuiDataGrid-columnsContainer"
      style="min-height: 56px; max-height: 56px; line-height: 56px;"
    >
      <div
        aria-rowindex="1"
        class="MuiDataGrid-colCellWrapper scroll"
        role="row"
        style="transform: translate3d(-0px, 0, 0); min-width: 1310px;"
      >
        <div
          aria-colindex="1"
          class="MuiDataGrid-colCell MuiDataGrid-colCellSortable MuiDataGrid-colCellNumeric"
          data-field="id"
          role="columnheader"
          style="width: 130px; min-width: 130px; max-width: 130px;"
          tabindex="-1"
        >
          <div
            class="MuiDataGrid-colCell-draggable"
            draggable="false"
          >
            <div
              class="MuiDataGrid-colCellTitleContainer"
            >
              <div
                aria-label="ID"
                class="MuiDataGrid-colCellTitle"
                title=""
              >
                ID
              </div>
            </div>
          </div>
          <div
            class="MuiDataGrid-columnSeparator"
            style="min-height: 56px; opacity: 1;"
          >
            <svg
              aria-hidden="true"
              class="MuiSvgIcon-root MuiDataGrid-iconSeparator"
              focusable="false"
              viewBox="0 0 24 24"
            >
              <path
                d="M11 19V5h2v14z"
              />
            </svg>
          </div>
        </div>
        <div
          aria-colindex="2"
          class="MuiDataGrid-colCell MuiDataGrid-colCellSortable MuiDataGrid-colCellNumeric"
          data-field="tenant_id"
          role="columnheader"
          style="width: 130px; min-width: 130px; max-width: 130px;"
          tabindex="-1"
        >
          <div
            class="MuiDataGrid-colCell-draggable"
            draggable="false"
          >
            <div
              class="MuiDataGrid-colCellTitleContainer"
            >
              <div
                aria-label="Tenant ID"
                class="MuiDataGrid-colCellTitle"
                title=""
              >
                Tenant ID
              </div>
            </div>
          </div>
          <div
            class="MuiDataGrid-columnSeparator"
            style="min-height: 56px; opacity: 1;"
          >
            <svg
              aria-hidden="true"
              class="MuiSvgIcon-root MuiDataGrid-iconSeparator"
              focusable="false"
              viewBox="0 0 24 24"
            >
              <path
                d="M11 19V5h2v14z"
              />
            </svg>
          </div>
        </div>
        <div
          aria-colindex="3"
          class="MuiDataGrid-colCell MuiDataGrid-colCellSortable"
          data-field="user_reference"
          role="columnheader"
          style="width: 250px; min-width: 250px; max-width: 250px;"
          tabindex="-1"
        >
          <div
            class="MuiDataGrid-colCell-draggable"
            draggable="false"
          >
            <div
              class="MuiDataGrid-colCellTitleContainer"
            >
              <div
                aria-label="Customer user reference"
                class="MuiDataGrid-colCellTitle"
                title=""
              >
                Customer user reference
              </div>
            </div>
          </div>
          <div
            class="MuiDataGrid-columnSeparator"
            style="min-height: 56px; opacity: 1;"
          >
            <svg
              aria-hidden="true"
              class="MuiSvgIcon-root MuiDataGrid-iconSeparator"
              focusable="false"
              viewBox="0 0 24 24"
            >
              <path
                d="M11 19V5h2v14z"
              />
            </svg>
          </div>
        </div>
        <div
          class="MuiDataGrid-cell MuiDataGrid-cellLeft"
          role="cell"
          style="min-width: 800px; max-width: 800px; line-height: 55px; min-height: 56px; max-height: 56px;"
        />
      </div>
    </div>
    <div
      class="MuiDataGrid-window"
      style="top: 56px; overflow-y: hidden;"
    >
      <div
        class="MuiDataGrid-dataContainer data-container"
        style="min-height: 119px; min-width: 1310px;"
      >
        <div
          class="MuiDataGrid-viewport"
          style="min-width: 0; max-width: 0; min-height: 104px; max-height: 104px;"
        >
          <div
            class="rendering-zone"
            style="max-height: 275px; width: 1310px; pointer-events: unset; transform: translate3d(-0px, -0px, 0);"
          >
            <div
              aria-rowindex="2"
              aria-selected="false"
              class="MuiDataGrid-row Mui-even"
              data-id="10190"
              data-rowindex="0"
              role="row"
              style="max-height: 52px; min-height: 52px;"
            >
              <div
                aria-colindex="0"
                class="MuiDataGrid-cell MuiDataGrid-cellRight"
                data-field="id"
                data-rowindex="0"
                data-value="10190"
                role="cell"
                style="min-width: 130px; max-width: 130px; line-height: 51px; min-height: 52px; max-height: 52px;"
                tabindex="0"
              >
                10190
              </div>
              <div
                aria-colindex="1"
                class="MuiDataGrid-cell MuiDataGrid-cellRight"
                data-field="tenant_id"
                data-rowindex="0"
                data-value="12201"
                role="cell"
                style="min-width: 130px; max-width: 130px; line-height: 51px; min-height: 52px; max-height: 52px;"
                tabindex="-1"
              >
                12201
              </div>
              <div
                aria-colindex="2"
                class="MuiDataGrid-cell MuiDataGrid-cellLeft"
                data-field="user_reference"
                data-rowindex="0"
                data-value="Xuser_ref"
                role="cell"
                style="min-width: 250px; max-width: 250px; line-height: 51px; min-height: 52px; max-height: 52px;"
                tabindex="-1"
              >
                Xuser_ref
              </div>
              <div
                class="MuiDataGrid-cell MuiDataGrid-cellLeft"
                role="cell"
                style="min-width: 800px; max-width: 800px; line-height: 51px; min-height: 52px; max-height: 52px;"
              />
            </div>
            <div
              aria-rowindex="3"
              aria-selected="false"
              class="MuiDataGrid-row Mui-odd"
              data-id="23541"
              data-rowindex="1"
              role="row"
              style="max-height: 52px; min-height: 52px;"
            >
              <div
                aria-colindex="0"
                class="MuiDataGrid-cell MuiDataGrid-cellRight"
                data-field="id"
                data-rowindex="1"
                data-value="23541"
                role="cell"
                style="min-width: 130px; max-width: 130px; line-height: 51px; min-height: 52px; max-height: 52px;"
                tabindex="-1"
              >
                23541
              </div>
              <div
                aria-colindex="1"
                class="MuiDataGrid-cell MuiDataGrid-cellRight"
                data-field="tenant_id"
                data-rowindex="1"
                data-value="96542"
                role="cell"
                style="min-width: 130px; max-width: 130px; line-height: 51px; min-height: 52px; max-height: 52px;"
                tabindex="-1"
              >
                96542
              </div>
              <div
                aria-colindex="2"
                class="MuiDataGrid-cell MuiDataGrid-cellLeft"
                data-field="user_reference"
                data-rowindex="1"
                data-value="Yuser_ref"
                role="cell"
                style="min-width: 250px; max-width: 250px; line-height: 51px; min-height: 52px; max-height: 52px;"
                tabindex="-1"
              >
                Yuser_ref
              </div>
              <div
                class="MuiDataGrid-cell MuiDataGrid-cellLeft"
                role="cell"
                style="min-width: 800px; max-width: 800px; line-height: 51px; min-height: 52px; max-height: 52px;"
              />
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
  <div>
    <div
      class="MuiDataGrid-footer"
    >
      <div />
      <div
        class="MuiTablePagination-root"
      >
        <div
          class="MuiToolbar-root MuiToolbar-regular MuiTablePagination-toolbar MuiToolbar-gutters"
        >
          <div
            class="MuiTablePagination-spacer"
          />
          <p
            class="MuiTypography-root MuiTablePagination-caption makeStyles-caption-1 MuiTypography-body2 MuiTypography-colorInherit"
          >
            1-2 of 2
          </p>
          <div
            class="MuiTablePagination-actions"
          >
            <button
              aria-label="Previous page"
              class="MuiButtonBase-root MuiIconButton-root MuiIconButton-colorInherit Mui-disabled Mui-disabled"
              disabled=""
              tabindex="-1"
              title="Previous page"
              type="button"
            >
              <span
                class="MuiIconButton-label"
              >
                <svg
                  aria-hidden="true"
                  class="MuiSvgIcon-root"
                  focusable="false"
                  viewBox="0 0 24 24"
                >
                  <path
                    d="M15.41 16.09l-4.58-4.59 4.58-4.59L14 5.5l-6 6 6 6z"
                  />
                </svg>
              </span>
            </button>
            <button
              aria-label="Next page"
              class="MuiButtonBase-root MuiIconButton-root MuiIconButton-colorInherit Mui-disabled Mui-disabled"
              disabled=""
              tabindex="-1"
              title="Next page"
              type="button"
            >
              <span
                class="MuiIconButton-label"
              >
                <svg
                  aria-hidden="true"
                  class="MuiSvgIcon-root"
                  focusable="false"
                  viewBox="0 0 24 24"
                >
                  <path
                    d="M8.59 16.34l4.58-4.59-4.58-4.59L10 5.75l6 6-6 6z"
                  />
                </svg>
              </span>
            </button>
          </div>
        </div>
      </div>
    </div>
  </div>

感谢您的帮助


你发布的示例代码存在一些问题。首先,组件没有显示columns从哪里来,这可能是你问题中最重要的细节。此外,你的测试包含了很多与你的问题似乎不相关的代码,例如模拟API、处理路由和执行变异。我建议你编写一个更简单的组件/测试来演示问题,并包括DOM(来自screen.debug)。 - srk
1
我也对DataGrid容器宽度为0的警告信息感到烦恼,而且我也在使用React测试库。使用哪种测试解决方案都不应该有影响。"网格宽度为0"的技巧看起来像是一种hack手段。 - Matt S
5个回答

26

我找到了一个解决方案:您可以设置datagrid的columnBuffer属性。
例如,对于8列,columnBuffer={8}


是的,但我仍然会收到MUI警告:“Material-UI:useResizeContainer - 网格的父级宽度为空”在日志中,这会混淆我的测试运行结果。 - gap
@gap 看起来这是一个包的问题,如果你更新到新版本,它就会被修复。错误被包裹在一些逻辑中,以测试测试环境是否为 JSDOM。 - antony
4
在较新的版本中,你可以通过disableVirtualization属性完全禁用虚拟化。这将强制网格呈现所有单元格。https://mui.com/components/data-grid/virtualization/#disable-virtualization - Jans Rautenbach

2
这与DataGrid无关,确保您的最外部容器默认占据100%的高度和宽度。我遇到了与下面所示相同的问题:

enter image description here

阅读警告后,我意识到容器需要调整大小,因此我将最外层容器的CSS更改为一个flexbox,并将整个宽度设置如下:
{
    display: flex;
    flex-direction: column;
    height: 100%;
    width: 100%;
}

如果你看到我的两张图片,你会注意到导致表格无法正确显示的差异。

enter image description here


这是正确答案 - metalheadcoder

1
这是由于虚拟化的缘故。您可以像这样禁用它。
<Gridtest disableVirtualization />

0

如果您想在真实数据网格中保留虚拟化但在测试中关闭它,您还可以设置全局模拟。

import { DataGridPro as OriginalDataGridPro, DataGridProProps } from '@mui/x-data-grid-pro';

// Sets up a mock for disableVirtualization on DataGrid
// Allows tests to check all columns
// Explained by https://github.com/mui/mui-x/issues/1151

export * from '@mui/x-data-grid-pro';
export const DataGridPro = (props: DataGridProProps) => {
    return <OriginalDataGridPro {...props} disableVirtualization />;
};

0
如果有其他人访问此页面并且仍然遇到 Material-UI: useResizeContainer: 如果您使用的是 happy-dom 环境而不是 jsdom,那么 mui-x 中的以下代码就是原因。
      // jsdom has no layout capabilities
      const isJSDOM = /jsdom/.test(window.navigator.userAgent);

      if (size.height === 0 && !errorShown.current && !props.autoHeight && !isJSDOM) {
        logger.error(
          [
            'The parent DOM element of the data grid has an empty height.',
            'Please make sure that this element has an intrinsic height.',
            'The grid displays with a height of 0px.',
            '',
            'More details: https://mui.com/r/x-data-grid-no-dimensions.',
          ].join('\n'),
        );
        errorShown.current = true;
      }

解决此问题的方法是修改用户代理。如果您正在使用vitest和happy-dom,从happy-dom 12.0.0开始,您可以通过将以下内容添加到您的vitest defineConfig中来欺骗它:
    environmentOptions: {
      happyDOM: {
        settings: {
          // eslint-disable-next-line @typescript-eslint/ban-ts-comment
          // @ts-ignore
          navigator: {
            userAgent: 'Mozilla/5.0 (linux) AppleWebKit/537.36 (KHTML, like Gecko) jsdom/22.1.0',
          },
        },
      },
    },

@ts-ignore 是因为在编写vitest时,它的类型定义中没有包含navigator.userAgent)
希望mui-x能够更新,以便在用户代理字符串中检测到HappyDOM的存在,这样就不再需要这个临时解决方法了。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接