在 useEffect 中的文本区域上设置行时,React 测试因 IndexSizeError 失败

React test fails with IndexSizeError when setting rows on a textarea in useEffect

我正在尝试在 React 测试库中实施测试,以验证我的 table 中的“添加新行”功能是否有效。

我先验证行数,然后我点击按钮,然后我想检查行数。

这是测试:

describe('Table Buttonbar', () => {
  it('Add new problem creates 3 new rows', async () => {
    const allVisibleRowsLength = allRows.filter(
      (row) => row.status !== PlanElementStatus.COMPLETED
    ).length;

    const plan = customRender(
      <Plan planId={mocks.planId} />,
      mocks.response
    );

    const buttonBar = await plan.findByRole('toolbar');
    const addProblemButton = await within(buttonBar).findByText('Problem');

    await waitFor(() => {
      expect(
        plan.getAllByTestId((el) => rowTypes.includes(el))
      ).toHaveLength(allVisibleRowsLength);
    });

    act(() => {
      userEvent.click(addProblemButton); //Fails here
    });

    await waitFor(() => {
      expect(
        plan.getAllByTestId((el) => rowTypes.includes(el))
      ).toHaveLength(allVisibleRowsLength + 3);
    });
  });

我得到的错误消息是这样的(我删除了很多 node_modules 堆栈跟踪):

console.error
    Error: Uncaught [IndexSizeError: The index is not in the allowed range.]

 console.error
    The above error occurred in the <TextArea> component

发生的情况是,当单击按钮时,3 个新行(1 个主行和 2 个子行)被添加到“编辑模式”中的 table,这意味着它不显示值,而是显示输入字段,包括一个文本区域。

此文本区域由自定义组件呈现,该组件用于在键入时动态调整文本区域的大小。

我发现组件中的错误代码是这样的:

//Sets the height of the textarea on mount so you dont have to type in it for it to resize(in case it already has a value)
  useEffect(() => {
    if (textAreaRef.current) {
      const currentRows = Math.ceil(
        textAreaRef.current.scrollHeight / fontSize - 1
      );

      textAreaRef.current.rows = minMax(currentRows, minRows, maxRows); // This is what triggers the error I believe
    }
  }, [minRows, maxRows]);

我已经通过简单地在各处添加 console.logs 来识别产生错误的代码。最后打印在 textAreaRef.current.rows = minMax(currentRows, minRows, maxRows)

之前

minMax 函数如下所示:

const minMax = (num: number, min: number, max: number): number =>
  Math.min(Math.max(num, min), max);

问题是,我不知道为什么会这样,也不知道我能做些什么。当我正常 运行 应用程序时,它工作得很好。它尝试将行设置为等于此处的值是 1,所以它“应该”没问题?

有人知道我在这里能做什么吗?

谢谢!

我在我的组件外计算了 fontSize,如下所示:

const fontSize = parseInt(
  getComputedStyle(document.documentElement)
    .getPropertyValue('--font-size')
    .replace('px', ''),
  10
);

const TextArea: React.FC<TextAreaProps> = ({
  minRows = 1,
  maxRows = 10,
  defaultValue,
  onChange,
}) => {
...

在测试中,返回的 NaN 导致了此错误。可能来自 Math.Ceil

解决方案是为测试添加一个回退值,如下所示:

  useEffect(() => {
    if (textAreaRef.current) {
      const currentRows = Math.ceil(
        textAreaRef.current.scrollHeight / (fontSize || 12) - 1 // fontSize fallback to make tests happy(calculated to NaN in tests)
      );
      textAreaRef.current.rows = minMax(currentRows, minRows, maxRows);
    }
  }, [minRows, maxRows]);