You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

@testing-library/user-event输入无效:React表单测试失败排查

React表单测试输入操作未生效问题

我编写了如下React表单测试代码:

import React from 'react';
import { render, screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import FormGenerator from '../index';

const func = () => 'dummy';

test('Enter value into the Form created with Rawdata', async () => {
  const user = userEvent.setup();
  render(
    <FormGenerator
      formInput={{ rawData: adhocData }}
      formAction={{ formSubmitAction: func }}
    />
  );

  const rawTextInputBox = await screen.findByRole('textbox', {
    name: /session/i,
  });
  user.type(rawTextInputBox, 'raw testing');

  await waitFor(() => {
    expect(rawTextInputBox.textContent).toBe('raw testing');
  });
});

const adhocData = {
  session: 'session',
  foo: 'foo',
  bar: 'bar',
};

测试失败,报错信息如下:

FAIL  src/__tests__/enterInputsRaw.test.tsx (73.531 s)
  ● Enter value into the Form created with Rawdata

    expect(received).toBe(expected) // Object.is equality

    Expected: "raw testing"
    Received: ""

    Ignored nodes: comments, script, style
    <html>
      <head />
      <body>
        <div>
          <div
            class="MuiGrid-root MuiGrid-container css-cofw97-MuiGrid-root"
          >
            <div
              class="MuiGrid-root MuiGrid-item MuiGrid-grid-xs-12 MuiGrid-grid-sm-12 MuiGrid-grid-md-12 MuiGrid-grid-lg-12 MuiGrid-grid-xl-12 plan-details-display css-ids664-MuiGrid-root"
            >
              <div
                class="MuiBox-root css-xi606m"
              >
                <h5
                  class="MuiTypography-root MuiTypography-h5 MuiTypography-alignCenter css-1n0cdgo-MuiTypography-root"
                >
                  Input Form
                  <p
                    class="MuiTypography-root MuiTypography-body1 MuiTypography-alignCenter css-d2ixlj-MuiTypography-root"
                  >
                    Please fill the form below
                  </p>
                </h5>
              </div>
            </div>
            <form
              novalidate=""
            >
              <div
                class="MuiGrid-root MuiGrid-container css-yqgy5m-MuiGrid-root"
              >
                <div
                  class="MuiGrid-root MuiGrid-item MuiGrid-grid-xs-12 MuiGrid-grid-sm-12 MuiGrid-grid-md-12 MuiGrid-grid-lg-12 MuiGrid-grid-xl-12 css-1idn90j-MuiGrid-root"
                >
                  <div
                    class="MuiFormControl-root MuiFormControl-fullWidth MuiTextField-root top99-user-input-field css-10uogjt-MuiFormControl-root-MuiTextField-root"
                    data-testid="session"
                  >
                    <label
                      class="MuiFormLabel-root MuiInputLabel-root MuiInputLabel-formControl MuiInputLabel-animated MuiInputLabel-shrink MuiInputLabel-filled MuiFormLabel-colorPrimary MuiFormLabel-filled Mui-focused 
MuiInputLabel-root MuiInputLabel-formControl MuiInputLabel-animated MuiInputLabel-shrink MuiInputLabel-filled css-123p841-MuiFormLabel-root-MuiInputLabel-root"
                      data-shrink="true"
                      for="session"
                      id="session-label"
                    >
                      session *
                    </label>
                    <div
                      class="MuiInputBase-root MuiFilledInput-root MuiFilledInput-underline MuiInputBase-colorPrimary MuiInputBase-fullWidth Mui-focused MuiInputBase-formControl MuiInputBase-multiline MuiInputBase-adornedEnd css-1pi9ckp-MuiInputBase-root-MuiFilledInput-root"
                    >
                      <textarea
                        aria-invalid="false"
                        aria-label="session"
                        class="MuiInputBase-input MuiFilledInput-input MuiInputBase-inputMultiline MuiInputBase-inputAdornedEnd css-15gz2ql-MuiInputBase-input-MuiFilledInput-input"
                        id="session"
                        name="session"
                        placeholder="session"
                        style="height: 0px; text-transform: lowercase; overflow: hidden;"
                      />
                      <textarea
                        aria-hidden="true"
                        class="MuiInputBase-input MuiFilledInput-input MuiInputBase-inputMultiline MuiInputBase-inputAdornedEnd css-15gz2ql-MuiInputBase-input-MuiFilledInput-input"
                        readonly=""
                        style="visibility: hidden; position: absolute; overflow: hidden; height: 0px; top: 0px; left: 0px; transform: translateZ(0); text-transform: lowercase; padding-top: 0px; padding-bottom: 0px; 
width: 100%;"
                        tabindex="-1"
                      />
                      <div
                        class="MuiInputAdornment-root MuiInputAdornment-positionEnd MuiInputAdornment-filled MuiInputAdornment-sizeMedium css-jv61v3-MuiInputAdornment-root"
                      >
                        <p
                          class="MuiTypography-root MuiTypography-body1 css-pdsqvv-MuiTypography-root"
                          data-mui-internal-clone-element="true"
                        >
                          🛈
                        </p>
                      </div>
                    </div>
                  </div>
                </div>
                <div
                  class="MuiGrid-root MuiGrid-item MuiGrid-grid-xs-12 MuiGrid-grid-sm-12 MuiGrid-grid-md-12 MuiGrid-grid-lg-12 MuiGrid-grid-xl-12 css-1idn90j-MuiGrid-root"
                >
                  <div
                    class="MuiFormControl-root MuiFormControl-fullWidth MuiTextField-root top99-user-input-field css-10uogjt-MuiFormControl-root-MuiTextField-root"
                    data-testid="foo"
                  >
                    <label
                      class="MuiFormLabel-root MuiInputLabel-root MuiInputLabel-formControl MuiInputLabel-animated MuiInputLabel-shrink MuiInputLabel-filled MuiFormLabel-colorPrimary MuiInputLabel-root MuiInputLabel-formControl MuiInputLabel-animated MuiInputLabel-shrink MuiInputLabel-filled css-123p841-MuiFormLabel-root-MuiInputLabel-root"
                      data-shrink="true"
                      for="foo"
                      id="foo-label"
                    >
                      foo *
                    </label>
                    <div
                      class="MuiInputBase-root MuiFilledInput-root MuiFilledInput-underline MuiInputBase-colorPrimary MuiInputBase-fullWidth MuiInputBase-formControl MuiInputBase-multiline MuiInputBase-adornedEnd css-1pi9ckp-MuiInputBase-root-MuiFilledInput-root"
                    >
                      <textarea
                        aria-invalid="false"
                        aria-label="foo"
                        class="MuiInputBase-input MuiFilledInput-input MuiInputBase-inputMultiline MuiInputBase-inputAdornedEnd css-15gz2ql-MuiInputBase-input-MuiFilledInput-input"
                        id="foo"
                        name="foo"
                        placeholder=

      21 |
      22 |   await waitFor(() => {
    > 23 |     expect(rawTextInputBox.textContent).toBe('raw testing');
         |                                         ^
      24 |   });
      25 | });
      26 |

从HTML输出可见目标文本框元素存在,但user.type(rawTextInputBox, 'raw testing');操作未生效,请问我哪里操作有误?


问题分析与解决方法
  • 未等待异步输入操作完成:user.type是异步函数,必须用await等待执行完毕,否则测试会在输入动作还没完成时就执行断言,导致获取空值。
  • 断言对象错误:textarea的内容存储在value属性中,而非textContent。textContent用于获取元素的文本节点内容,表单输入控件的值需要通过value属性获取。

修正后的测试代码:

import React from 'react';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import FormGenerator from '../index';

const func = () => 'dummy';

test('Enter value into the Form created with Rawdata', async () => {
  const user = userEvent.setup();
  render(
    <FormGenerator
      formInput={{ rawData: adhocData }}
      formAction={{ formSubmitAction: func }}
    />
  );

  const rawTextInputBox = await screen.findByRole('textbox', {
    name: /session/i,
  });
  // 等待输入操作完成
  await user.type(rawTextInputBox, 'raw testing');

  // 断言value属性而非textContent
  expect(rawTextInputBox).toHaveValue('raw testing');
});

const adhocData = {
  session: 'session',
  foo: 'foo',
  bar: 'bar',
};

内容的提问来源于stack exchange,提问作者moys

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 14:07:32