@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
相关产品推荐
相关产品推荐

